
/**
 * 流程定义数据格式,默认初始化
 * @author liys 201903
 */
define('flowdesigner/element/FlowInit',['require','jquery'],function(require) {
    var $ = require('jquery');

    var FlowInit = function (opts) {

    };
    FlowInit.prototype ={
        //初始化一个空的定义数据对象
        initFlow:function(fd){
            var participantId = 'Author;SecondAuthor;Reader;Done;Manager;Creator';
            //'主办;协办;读者;已办;管理员;创建者'
            var participantName='';
            var pName = fd.getOptions('participantsName');
            $.each(participantId.split(';') ,function(i,key){
                participantName += ';' + pName[key];
            });
            participantName = participantName.substring(1);
            return {
                flowInfo: {
                    id: '',              //流程定义数据在库表中对应的id
                    flowId: 'NewFlowId',//流程id,用来启动实例时指定
                    flowName: fd.getLang('static.newFlow'),   //流程名称
                    active: 0,      //是否发布状态0=在修改,1=已发布,2=在修改
                    version: 1,     //流程版本号,如果流程状态为1已发布,再次保存时,版本号自动+1
                    flowType: {     //流程类型
                        id: '',   //类型id
                        name: ''  //类型名称
                    },

                    creator: '',    //创建人
                    created: '',    //创建时间
                    modifier: '',   //修改人
                    update: '',     //更新时间

                    saveLocal: '0', //实例在打开时是否保存到本地
                    // releaseStatus: '',
                    openTodoFlag: '1',
                    updateToDB: true,//是否保存节点信息到数据中

                    flowlimit: {    //办理时限
                        days: 0,    //时限长度
                        type: 1     //时限类型,0=工作日,1=自然日,(2=小时,3=分钟)
                    },
                    //启动权限校验默认实现类
                    startRuleClassName: 'com.horizon.wf.rule.defa.StartRuleDefault',
                    //实例打开时判断参与者权限的默认实现类
                    checkRoleClassName: 'com.horizon.wf.rule.defa.CheckRoleForOpenInstanceDefault',
                    //业务数据处理的默认实现类
                    relationRuleClassName: 'com.horizon.wf.rule.defa.RelationRuleDefault',
                    //实例日志记录默认实现类
                    trackLogClassName: 'com.horizon.wf.rule.defa.TrackLogDefault',

                    memo: '',       //备注

                    participants: {     //参与者默认只有读者
                        Reader: {
                            authId: 'Reader',
                            authName: pName['Reader'],
                            person: '',     //个人
                            dept: '',       //部门
                            group: '',      //群组
                            position: '',   //岗位
                            msgFlag: ''     //消息类型
                        }
                    },

                    forms: {          //流程表单列表
                        //通过initFlowForm()来获取一个新的表单对象
                        //默认流程跟踪
                        FlowTrack: {    //默认流程跟踪表单
                            id: 'FlowTrack',
                            name: fd.getLang('html.flow.form.table.trackname')
                        }
                    },

                    vars: {
                        //流程变量,默认为空,
                        //通过initVar()来获取一个新的变量对象
                        //使用varId作为vars的key来存储变量对象
                        //例如:
                        // A:{varID:A,....}
                    },
                    //参与者类型,目前只支持下面6种
                    participantId: participantId,
                    participantName: participantName
                    // participantAuth: 'Author_DO;SecondAuthor_DO;Reader_DO;Done_DO;Manager_DO;Creator_DO'

                },
                process: {},
                mapData: {
                    nodeNum: 1,
                    routeNum: 1,
                    flowId: 'NewFlowId',
                    flowName:'',
                    nodes: {
                        // Node1: {
                        //     id: 'Node1',     //节点id
                        //     sub: 0,          //是否含有子流程(用来判断显示图标的)
                        //     name: '节点1',    //节点名称
                        //     nodeType: 210,   //节点类型
                        //     y: 344,          //坐标y
                        //     x: 519           //坐标x
                        // }
                    },
                    lines: {
                        // line3:{
                        //     id: 'Line3',
                        //     name: '新路由3',
                        //     lineType: 1,        //路由类型1=直线,2=折线
                        //     from: 'Node2',      //开始节点
                        //     to: 'Node3',        //结束节点
                        //     x1: 232,            //开始节点坐标x
                        //     y1: 124,            //开始节点坐标y
                        //     x2: 337,            //结束节点坐标x
                        //     y2: 126,            //结束节点坐标y
                        //     point:null          //折线时,如果时4段线的中间线段点坐标(记录拖动后的坐标,为空时自动计算)
                        // }
                    }
                }
            };
        },
        //流程变量对象
        initVar: function () {
            return {
                varId: '',          //变量
                varName: '',        //变量名称
                memo: '',           //变量说明
                initValue: '',     //默认值
                len: '',            //长度
                varType: 1,        //类型:1字符,2数字,3布尔,4日期,5日期时间,6组织机构,10其他
                varFrom: ''        //从表单字段获取时对应的字段
            };
        },
        //流程表单对象
        initFlowForm:function(){
          return {
              id: '',   //表单id
              name: '', //表单名称
              group: '',//表单分组
              type: '',   //表单类型(自定义/定制/...用于解析时能区分使用不同的方式来解析)
              isMain: 0,  //是否主表单
              tableId: '',    //表单对应的数据库表名
              data: '',       //自定义类型的表单数据
              version: 0      //使用表单的版本号
          };
        },
        //参与者对象
        initAuth:function () {
            return {
                authId: '',//从participantId中获取
                authName: '',//从participantName中获取
                person: '', //个人
                dept: '',   //部门
                group: '',  //群组
                position: '',//岗位

                passNode: '',       //control中勾选[跳过指定节点办理人时]指定的节点id
                control: 'FreeSelect;AgentFlag',//控制项
                //OuterSelect;ManualSelect;FreeSelect;AutoPass;
                //PassNodeUser;PassCurUser;AgentFlag;OnlySelectUser
                /**
                 <Item id='OuterSelect'>由外部设置办理人</Item>
                 <Item id='ManualSelect'>需要从设置列表中选择办理人</Item>
                 <Item id='FreeSelect'>办理人为空时，允许自由选择</Item>
                 <Item id='AutoPass'>办理人为空时，跳过此节点</Item>
                 <Item id='PassCurUser'>办理人包含当前人时，跳过此人</Item>
                 <Item id='PassNodeUser'>跳过指定节点的办理人</Item>
                 <Item id='AgentFlag'>代办设置生效</Item>
                 <Item id='OnlySelectUser'>仅允许选择人员</Item>
                 */
                customer: {          //自定义
                    className:'',   //解析memo内容的实现类
                    memo: '',       //自定义内容
                    check: 0        //是否启用0=不启用,1=启用并忽略其他设置
                },
                formField: {        //从字段中获取
                    union: '2',     //默认并集处理,解析部分暂时不支持交集处理,所以此处只能为2
                    name: '',       //对应的字段名称
                    pageId: ''      //所属的表单ID
                },

                flowVar: {          //从流程变量中获取
                    union: '2',     //默认并集处理,解析部分暂时不支持交集处理,所以此处只能为2
                    name: ''        //变量id
                },

                rule: {             //根据规则获取
                    id: '',         //规则对应的数据id
                    text: '',       //规则显示的文本内容
                    script: ''      //规则可以执行的脚本内容
                },

                relation: [
                    // 按关系获取,可以是多个
                    //根据initRelation获取一个新的关系对象
                ],

                msgFlag: ''         //消息发送方式
                /*
                <Item id='Mail'>邮件</Item>
                <Item id='Msg'>系统消息</Item>
                <Item id='SMS'>短信</Item>
                <Item id='IM'>即时消息</Item>
                 */
            };
        },
        //参与者对象中的关系定义对象
        initRelation:function(){
            return {
                node: '',      //相对的节点,空==无,1==上一节点,节点id==指定的节点
                base: '',      //关系基准   1==无,2==流程启动者,3==当前执行人
                relation: '',  //关系类型
                /*
                <Relation data='1'>同部门人员</Relation>
                <Relation data='2'>直接部门领导</Relation>
                <Relation data='3'>所有上级领导</Relation>
                <Relation data='4'>直接下属</Relation>
                <Relation data='5'>所有下属</Relation>
                <Relation data='6'>上级主管领导</Relation>
                <!-- <Relation data='7'>领导对应秘书</Relation> -->
                <!-- <Relation data='8'>秘书对应领导</Relation> -->
                <Relation data='9'>上一级部门所有人员(含子部门)</Relation>
                <!-- <Relation data='10'>流程启动者</Relation> -->
                <Relation data='16'>上一级部门所有人员(不含子部门)</Relation>
                <Relation data='15'>部门接口人</Relation>
                <Relation data='17'>上级岗位</Relation>
                <Relation data='18'>上级岗位人员</Relation>
                <Relation data='19'>下级岗位</Relation>
                <Relation data='20'>下级岗位人员</Relation>
                 */
                union: '2',
                text: ''
            };
        },
        //节点激活设置
        initStartMode:function(){
            return {
                type:0
                //类型:0=人工(也就是到达激活时)不需要,1=定时,2=消息,3=信号
                //1.定时需要的参数
                // timeClassName: '',      //执行接口实现类
                // timeDate: '',           //定时的时间(对应流程变量)
                // timeRetry: 1,           //是否允许重试1=允许0=不允许
                // num: 1,                 //重试次数
                // timeCycle: '1' ,         //重试周期

                //2.消息激活时的参数
                // msgPara: 'A',           //参数(对应流程变量)
                // msgClass: '',           //实例类
                // msgId: '',              //消息id(用途不明)
                // msgName: '1',           //名称(用途不明)
                // msgFrom: '',            //来自(用途不明)
                // msgTo: '',              //到哪(用途不明)
                // msgType: '2',           //消息类型(用途不明)

                // 3.信号激活时的参数
                // signalPara: '',             //信息参数(对应流程变量)
                // signalClass: '',            //实现类
            };
        },
        //节点设置信息
        initProcess:function(){
            return {
                id: '',     //节点id
                name: '',   //节点名称
                nodeType: 10,   //节点类型
                nxtSelType: 2,//后续分支选择类型(0=全选,1=多选,2=单选)
                className: '',//默认时限类
                //节点激活类型
                startMode: {
                    type:0
                    //参考initStartMode()方法中的信息
                },
                limit: {        //节点时限
                    lType: 1,   //时限类型(0=工作日,1=自然日,(2=小时,3=分钟)
                    lDate: 0,   //时限数量
                    wDate: 0,   //警告时限
                    num: 0     //催办数
                },
                memo: '',   //备注
                special:{
                    //不同的节点需要的不同参数
                    //---->多人单一节点 是否允许抢占
                    // grab:'0',    //1=允许0=不允许

                    //----->多人并行
                    // asyn: 0,        //是否异步1=异步,0=同步
                    // //多人并行处理的通过方式设置(如果是异步处理,则忽略此设置)
                    // //
                    // passType: 4,//1.参与者超过X个已处理,2.指定处理人中的任意一个已处理,
                    //             // 3.指定处理人全部处理,4.所有参与者已处,5.扩展规则
                    // passPara: '',    //对应参数内容
                    // lock: 1,    //多人处理时,是否在编辑时锁定文档(独占打开)

                    //----->内部循环节点
                    // progressivelyClassName:'',//实现类

                    //----->自动节点
                    // robotClassName:'',

                    //----->引擎交互
                    // clusterClassName:'',    //引擎交互交互节点数据打包实现类的路径
                    // clusterUrl:'',          //引擎交互交互节点节后数据的服务器路径(根据数据交互方式来确定)
                    // clusterInteractive:'',  //系统交互处理类的全路径名称

                    //----->网关合并,网关分支
                    // gateway:{
                    //     className:'',   //实现类与规则互斥
                    //     id:'',          //规则数据id
                    //     script:'',      //可执行的规则脚本内容
                    //     text:''         //用于显示的规则内容
                    // },

                    //----->合并节点(合并网关的submitAgain,cancelOther也是存在此处)
                    // merger:{
                    //     mergerAll: 0,    //合并所有能到达的分支
                    //     submitAgain: 0,  //离开后,其他分支到底允许重新激活
                    //     reSelect: 0,     //重新激活时,允许重新选择办理人
                    //     cancelOther: 0,  //激活后,其他未到达的分支取消
                    //
                    //     activeType: 4,//激活方式:1.分支超过X个,2.指定分支中任意一个到达,3,指定分支全部到达,
                    //                   //       4.所有分支到达后激活,5.立即激活,6.扩展规则
                    //     activePara: '',//对应参数
                    //
                    //     leaveType: 4,//离开方式:1.分支已到X个,2.指定分支中任意一个到达,3.指定分支全部到达,
                    //                  //       4.所有分支到达,5.自行确定,6.扩展规则
                    //     leavePara: ''//对应参数
                    // }
                },

                entry: {
                    className: '',//节点进入实现类,与规则互斥
                    id:'',
                    script:'',
                    text:''
                },
                leave: {
                    className: '',
                    id:'',
                    script:'',
                    text:''
                },
                events:{},
                exceptions:{},
                paras:{},
                subflow:{flows:{},wait:1,multi:0},
                authDo: {
                    //通过initDo()获取对应的参与者设置参数,key=id
                },
                participants: {
                    //通过intAuth()获取参与者设置参数,key=id
                },
                transitions: {
                    //通过initRoute()获取路由设置参数,key=id
                }
            };
        },

        //不同参与者的设置信息
        initDo: function () {
            return {
                id: '',//对应的参与者类型participantId: 'Author;SecondAuthor;Reader;Done;Manager;Creator',
                forms: {        //参与者可用的表单设置
                    dfId: '',  //默认显示的表单id
                    form: {
                        FlowTrack: {    //流程跟踪,默认应该要显示
                            id: 'FlowTrack',
                            buttons: '',
                            fieldControlId: 'alleditable'
                        }
                        //initNodeForm()获取,id作为form的key
                    }
                },
                buttons: {  //按钮操作
                    backNodes:'',   //拿回约束
                                    //其他约束将来也放在这个地方
                    actions: {      //按钮
                        // 通过initAction()获取一个按钮对象,id作为actions的key
                        // readed: {
                        //     id: '',
                        //     name: '',
                        //     reName: '',
                        //     mplClass: ''
                        // }
                    }
                }
            };
        },

        //节点上根据不同身份设置的操作对象
        initAction:function(){
            return {
                id: '',         //按钮id
                name: '',       //按钮默认名称
                reName: '',     //按钮重置的名称
                implClass: ''   //按钮执行的类路径
            };
        },

        //节点上的表单设置对象,在操作页签中根据不同身份不同
        initNodeForm:function(id){
            return {
                id: '',     //表单id
                buttons: '',//表单上的自定义操作(被选中的)
                fieldControlId: ''//表单字段权限设置对应的数据id
            };
        },

        //子流程标签中,每条子流程数据对象
        initSubFlow:function(){
            return {
                id: '',
                name: '',
                paras:[
                    //参数传递的信息,
                    //initSubFlowPara()
                ]
            };
        },
        //子流程数据对象中的流程变量参数设置对象,
        initSubFlowPara:function(){
            return {
                mainVar:'', //主流程变量id
                subVar:'',  //子流程变量id
                type:1        //交互方式:1=主流程输出至子流程,2=主流程接受子流程,3=双向输出
            };
        },

        //事件对象
        initEvent:function(){
            return {
                id: '',     //唯一标示
                name: '',   //事件名称
                className: '',//事件实现类
                type: ''    //事件类型
            };
        },

        // 异常对象
        initException:function(){
            return {
                code: '',   //异常代码
                name: '',   //异常名称
                dealType:'',//异常处理类型0 自定义 1 无 2 跳转 3 挂起 4 终止
                deal: '',   //处理方式根据类型不同,对应的内容不同
                user: '',   //消息接收人
                msg: ''     //发送消息
            };
        },

        //节点中的指向路由对象
        initRoute:function(){
            return {
                id: '',         //路由id
                name: '',       //路由名称
                nodeId: '',     //指向节点id
                nodeName: '',   //指向节点名称
                nodeType: 10,   //指向节点类型
                sort:1,         //路由排序,序号
                condition: '',  //路由条件内容
                bCondition: '', //转码后的条件内容,为避免中文乱码
                rule: {         //路由条件扩展判断时需要的实现类或者是规则脚本
                    id: '',     //规则id(用于存储规则信息的数据id)
                    text: '',   //规则显示时的内容
                    rule: '',   //规则可以执行的脚本内容
                    className: ''//路由条件扩展判断时的实现类,跟规则互斥
                    //className不为空时,id,text,rule无效
                },
                //executions,include只有虚拟节点指向时才需要
                // include: '', //包含哪些节点
                // executions: '',//排除哪些节点
                memo: ''
            };
        },

        //节点参数对象
        initPara:function () {
            return {
                id: '',        //参数id
                name: '',       //参数名称
                value: ''       //参数默认值
            };
        }
    };

    return new FlowInit();
});
/**
 * 泳道对象
 * @author liys 201903
 */
define('flowdesigner/element/Swimlane',['require','jquery','zrender'],function (require) {

    var $ = require('jquery'),
        zRender = require('zrender');

    var Swimlane = function (opts) {
        for (var name in opts) {
            this[name] = opts[name];
        }
        this._setShape();
    };

    Swimlane.prototype = {
        constructor: Swimlane,
        __Flowdesigner: null,
        __drawLayer: null,
        id: 'swimlan',
        name: null,     //泳道标题,默认流程名称
        lanetype: 1,     //泳道的方向,1=纵向,2=横向
        lanenum: 1,      //泳道数目

        lanewidth: [],   //泳道宽度
        lanename: [],    //泳道名称

        defwidth: 200,
        txtheight: 30,      //文字框的默认高度
        map: {},

        zrGroup: null,
        titleShape: null,//泳道标题对象
        laneShape: [], //泳道对象,多个
        textShape: [], //泳道对应的文字显示,多个,跟laneShape匹配
        textGroup: [], //水平泳道名称显示,需要竖向排列(需要单独处理)
        dragShape: [],  //泳道拖动点
        laneGroup: [],  //每个泳道的组

        delTitleShape: null,
        delLaneShape: [],

        selPos: null,

        maxWidth: 0,     //最大宽度
        maxHeight: 0,    //最大高度,用于画布大小发生变化时判断

        cutWidth: 0,        //记录可以裁剪的最大宽度或者高度

        _setShape: function () {
            this.maxWidth = this.__Flowdesigner.zrender.getWidth() - this.txtheight - 25;
            this.maxHeight = this.__Flowdesigner.zrender.getHeight() - 2 * this.txtheight - 25;
            if (this.lanetype == 1 && this.map['laneHeight']) {
                this.maxHeight = this.map['laneHeight'];
            }
            if (this.lanetype == 2 && this.map['laneHeight']) {
                this.maxWidth = this.map['laneHeight'];
            }

            this._makeTitleShape(this._makeLaneShape());
        },
        _makeTitleShape: function (width) {
            var self = this;
            var tmpwidth = this.lanetype == 1 ? width : (this.maxWidth + this.txtheight);
            this.titleShape = new zRender.Rect({
                __swimlane: self,
                z: self.__drawLayer.getZLevel(self.__Flowdesigner.zArr.swimlane),
                style: {
                    lineWidth: 1,
                    fill: '#f0f0f0',
                    stroke: '#bebebe',
                    strokeNoScale: true, //描边粗细不随缩放而改变，false 则会根据缩放同比例缩放描边粗细。
                    transformText: true, //文字是否跟随变换效果，仅对 Path 或 Image 元素有效
                    text: self.name,
                    textFill: '#000',
                    textPosition: 'inside',
                    textAlign: 'center',
                    textVerticalAlign: 'center'
                },
                shape: {
                    x: 1,
                    y: 0,
                    width: tmpwidth,
                    height: self.txtheight
                }
            });
            if (this._showTypeisDesigner()) {
                this.titleShape
                    .on('click', function () {
                        self._ckSwimlaneTitle();
                    })
                    .on('contextmenu', function (param) {
                        self._showContextMenu(param);
                    });
                this.delTitleShape = new zRender.Image({
                    __swimlane: this,
                    z: self.__drawLayer.getZLevel(self.__Flowdesigner.zArr.selected),
                    position: [0, 0],
                    style: {
                        x: tmpwidth / 2,
                        y: this.txtheight,
                        image: this.__Flowdesigner.options.flownode.image['deleteurl'],
                        width: 13,
                        height: 11
                    },
                    onclick: function (param) {
                        // console.log(this.name + '要删除了哦');
                        self._deleteAllClick();
                    }
                });
            }
        },
        _makeLaneShape: function (name) {
            var self = this;
            var pos = 0;
            this.laneShape = [];
            this.textShape = [];
            this.textGroup = [];
            this.dragShape = [];
            this.delLaneShape = [];
            this.laneGroup = [];

            for (var i = 0; i < this.lanenum; i++) {
                if (!this.lanewidth[i]) {
                    this.lanewidth.push(this.defwidth);//默认宽度200
                }
                if (!this.lanename[i]) {
                    this.lanename.push(self.__Flowdesigner.getLang('static.swimlanes') + (i + 1));
                }
                if (i > 0) {
                    pos += this.lanewidth[i - 1];
                }

                this._addLane(pos, i);
            }
            pos += this.lanewidth[this.lanenum - 1];
            self.cutWidth = pos;
            return pos;
        },
        _addLane: function (pos, i) {
            var self = this;
            var name = self.lanename[i];
            var title = new zRender.Rect({
                __swimlane: self,
                z: self.__drawLayer.getZLevel(self.__Flowdesigner.zArr.swimlane),
                style: {
                    opacity: 1,
                    lineWidth: 2,
                    fill: '#fff',
                    stroke: '#bebebe',
                    strokeNoScale: true, //描边粗细不随缩放而改变，false 则会根据缩放同比例缩放描边粗细。
                    transformText: true, //文字是否跟随变换效果，仅对 Path 或 Image 元素有效
                    text: this.lanetype == 1 ? name : '',
                    textFill: '#000',
                    textPosition: 'inside',
                    textAlign: 'center',
                    textVerticalAlign: 'center'
                },
                shape: this.lanetype == 1 ?
                    {
                        x: pos + 1,
                        y: this.txtheight + 1,
                        width: this.lanewidth[i],
                        height: this.txtheight
                    } :
                    {
                        x: 1,
                        y: pos + this.txtheight + 1,
                        width: this.txtheight,
                        height: this.lanewidth[i]
                    }
            });

            self._bindEvent(title, self.textShape);

            this.textShape.push(title);

            if (this.lanetype == 2) {
                var x = 1 + this.txtheight / 2,
                    y = pos + this.txtheight + 1 + this.lanewidth[i] / 2;
                this.textGroup.push(this._drawText(name, x, y, this.lanewidth[i]));
            }

            var rectpoint = this._getRectPoints(pos, i);
            this.laneShape.push(new zRender.Polyline({
                cursor: 'point',
                z: self.__drawLayer.getZLevel(self.__Flowdesigner.zArr.swimlane),
                style: {
                    lineWidth: 1,
                    stroke: '#bebebe',
                    lineJoin: 'round'
                },
                shape: {
                    points: rectpoint
                }
            }))
            if (this._showTypeisDesigner()) {
                var shape = this._getDragPoint(rectpoint);
                this.dragShape.push(new zRender.Circle({
                    __swimlane: self,
                    invisible: true,   //图形是否不可见，为 true 时不绘制图形，但是仍能触发鼠标事件。
                    z: self.__drawLayer.getZLevel(0),                //不现实的时候放入最底层
                    style: {
                        stroke: '#FF8600',
                        fill: 'yellow',
                        opacity: '1'
                    },
                    position: [0, 0],
                    shape: {
                        cx: shape.cx,
                        cy: shape.cy,
                        r: 4
                    },
                    draggable: true, //只有中间点允许拖动
                    ondrag: function (param) {
                        self._dragSwimlanePoint(param.event.zrX, param.event.zrY);
                    }
                }));
                this.delLaneShape.push(new zRender.Image({
                    __swimlane: self,
                    z: self.__drawLayer.getZLevel(self.__Flowdesigner.zArr.selected),
                    position: [0, 0],
                    style: {
                        x: shape.x,
                        y: shape.y,
                        image: this.__Flowdesigner.options.flownode.image['deleteurl'],
                        width: 13,
                        height: 11
                    },
                    onclick: function (param) {
                        // console.log(self.name + '要删除了哦');
                        var nowPos = $.inArray(this, self.delLaneShape);
                        self._deleteOneClick(nowPos);
                    }
                }));
            }
        },
        _bindEvent: function (objCanvas, arr) {
            if (this._showTypeisDesigner()) {
                var self = this;
                objCanvas
                    .on('mouseover', function (param) {
                        var nowPos = $.inArray(this, arr);
                        //不能直接使用pos,因为在删除泳道后,pos的值是会发生变化的
                        self.__Flowdesigner.showTitle(self.lanename[nowPos], {x: param.event.zrX, y: param.event.zrY});
                    })
                    .on('mouseout', function () {
                        self.__Flowdesigner.hideTitle();
                    })
                    .on('click', function () {
                        var nowPos = $.inArray(this, arr);
                        //不能直接使用pos,因为在删除泳道后,pos的值是会发生变化的
                        self._ckSwimlane(nowPos);
                    })
                    .on('contextmenu', function (param) {
                        var nowPos = $.inArray(this, arr);
                        //不能直接使用pos,因为在删除泳道后,pos的值是会发生变化的
                        self._showContextMenu(param, nowPos);
                    });
            }
        },
        // 绘制纵向文本
        _drawText: function (str, cx, cy, height) {
            var self = this;
            var group = new zRender.Group({
                cx: cx,
                cy: cy,
                height: height
            });
            self._chgDrawText(group, str);
            self._bindEvent(group, self.textGroup);
            return group;
        },
        _chgDrawText: function (group, str) {
            var self = this;
            group.dirty();
            group.removeAll();
            var cx = group.cx, cy = group.cy, height = group.height;

            var len = str.length;
            var truncate = false;
            if (len * 14 > height) {
                len = parseInt(height / 14) - 2;
                truncate = true;
            }
            for (var i = 0; i < len; i++) {
                var y = 14 * i;
                var text = self._makeText(str.charAt(i), y);
                group.add(text);
            }
            if (truncate) {
                group.add(self._makeText("...", len++ * 14));
            }

            cy -= len * 7 - 5;
            group.attr({
                position: [cx, cy]
            });
        },
        _makeText: function (text, y) {
            var self = this;
            return new zRender.Text({
                __swimlane: self,
                z: self.__drawLayer.getZLevel(self.__Flowdesigner.zArr.swimlane),
                position: [2, y],
                style: {
                    text: text,
                    fontSize: 14,
                    // textBackgroundColor: '#FFF',
                    textFill: '#000',
                    textPosition: 'inside',
                    textAlign: 'center',
                    textVerticalAlign: 'center'
                }
            });
        },
        _getRectPoints: function (pos, i) {
            var x, y, width, height;
            if (this.lanetype == 1) {
                x = pos + 1;
                y = 2 * this.txtheight + 1;
                width = this.lanewidth[i];
                height = this.laneShape[0] ? this.laneShape[0].shape.points[1][1] - y : this.maxHeight;
            } else {
                x = 1 + this.txtheight;
                y = pos + this.txtheight + 1;
                width = this.laneShape[0] ? this.laneShape[0].shape.points[2][0] - x : this.maxWidth;
                height = this.lanewidth[i];
            }

            return [
                [x, y],
                [x, y + height],
                [x + width, y + height],
                [x + width, y],
                [x, y]
            ];
        },
        _getDragPoint: function (rectpoint) {
            return this.lanetype == 1 ? {
                    cx: rectpoint[2][0],
                    cy: (rectpoint[2][1] + rectpoint[3][1]) / 2,
                    x: (rectpoint[0][0] + rectpoint[3][0]) / 2,
                    y: rectpoint[0][1]

                } :
                {
                    cx: (rectpoint[2][0] + rectpoint[1][0]) / 2,
                    cy: rectpoint[2][1],
                    x: rectpoint[0][0],
                    y: (rectpoint[0][1] + rectpoint[1][1]) / 2
                };
        },

        addOneLane: function () {
            this.lanename[this.lanenum] = this.__Flowdesigner.getLang('static.swimlanes') + (this.lanenum + 1);
            this.lanewidth[this.lanenum] = this.defwidth;
            var pos = 0;
            for (var i = 0; i < this.lanenum; i++) {
                pos += this.lanewidth[i];
            }
            this._addLane(pos, this.lanenum);

            var group = new zRender.Group();
            this.zrGroup.add(group);
            this.laneGroup.push(group);
            group.add(this.textShape[this.lanenum]);
            group.add(this.laneShape[this.lanenum]);
            group.add(this.dragShape[this.lanenum]);

            //如果是竖直泳道,还需要对标题长度进行修改
            if (this.lanetype == 1) {
                var width = this.titleShape.shape.width + this.lanewidth[this.lanenum];
                this.titleShape.attr({
                    shape: {
                        width: width
                    }
                });
                this.delTitleShape.attr({
                    style: {
                        x: width / 2
                    }
                });
            } else {
                group.add(this.textGroup[this.lanenum]);
            }
            this.lanenum++;
            this._reviewMap();
        },
        _delOneLane: function (pos) {
            this.selPos = null;
            if (this.lanenum == 1) {
                //全部删除了
                this._removeSelfFromZr();
                return;
            }

            this.lanenum--;
            // var pos =  $.inArray(obj,this.textShape);
            var point = this.laneShape[pos].shape.points[0];

            this.zrGroup.remove(this.laneGroup[pos]);
            this.laneGroup.splice(pos, 1);

            this.lanename.splice(pos, 1);
            this.lanewidth.splice(pos, 1);

            this.textShape.splice(pos, 1);
            this.laneShape.splice(pos, 1);
            this.dragShape.splice(pos, 1);

            this.delLaneShape.splice(pos, 1);


            //从pos开始重新移动位置
            this._refreshSwim(point[0], point[1], pos);

            this._reviewMap();
        },
        //显示和隐藏删除
        _ckSwimlaneTitle: function () {
            this.__Flowdesigner.cancelSel();
            // this.zrGroup.add(this.delTitleShape);
        },
        _ckSwimlane: function (pos) {
            var self = this;
            this.__Flowdesigner.cancelSel();
            if (this.__drawLayer.isScale()) {
                return;
            }
            // var pos = $.inArray(obj,this.textShape);
            this.selPos = pos;
            this._chgSelected(pos, false);
        },
        cancelSel: function () {
            if (!(this.selPos == null || this.selPos == undefined)) {
                this._chgSelected(this.selPos, true);
            }
            this.selPos = null;
            // this.zrGroup.remove(this.delTitleShape);
        },
        _chgSelected: function (pos, hidden) {
            this.__Flowdesigner.selSwimlaneHandler = hidden ? null : this;
            this.dragShape[pos].attr({
                z: this.__drawLayer.getZLevel(hidden ? 0 : this.__Flowdesigner.zArr.selected),
                invisible: hidden
            });
            this.laneShape[pos].attr({
                z: this.__drawLayer.getZLevel(hidden ? 1 : this.__Flowdesigner.zArr.selected),
                style: {
                    stroke: hidden ? '#bebebe' : '#2b9727'
                }
            });
        },
        _chgSwimlaneTitle: function () {
            var self = this;
            $.confirm({
                title: self.__Flowdesigner.getLang('static.info'),
                content: self.__Flowdesigner.getLang('static.inputswimname')
                    + '<input type="text" value="' + self.name + '" name="tmpText">',
                type: 'blue',
                icon: 'glyphicon glyphicon-info-sign',
                buttons: {
                    ok: {
                        text: self.__Flowdesigner.getLang('static.ok'),
                        btnClass: 'btn-primary',
                        action: function () {
                            var name = $('input[name="tmpText"]').val();
                            self.setSwimlaneTitle(name);
                        }
                    },
                    cancel: {
                        text: self.__Flowdesigner.getLang('static.cancel'),
                        btnClass: 'btn-primary'
                    }
                }
            });
        },
        setSwimlaneTitle: function (title) {
            var self = this;
            self.name = title;
            self.map.name = self.name;
            self.titleShape.attr({
                style: {
                    text: self.name
                }
            });
        },
        _chgSwimlaneWidth: function () {
            var self = this;
            $.confirm({
                title: self.__Flowdesigner.getLang('static.info'),
                content: (self.lanetype == 1 ? self.__Flowdesigner.getLang('static.inputswimHeight') : self.__Flowdesigner.getLang('static.inputswimWidth'))
                    + '<input type="text" value="' + (self.lanetype == 1 ? self.laneShape[0].shape.points[1][1] - 61 : self.laneShape[0].shape.points[2][0] - 31) + '" name="tmpText" oninput="value=value.replace(/[^\\d]/g,\'\')">',
                type: 'blue',
                icon: 'glyphicon glyphicon-info-sign',
                buttons: {
                    ok: {
                        text: self.__Flowdesigner.getLang('static.ok'),
                        btnClass: 'btn-primary',
                        action: function () {
                            var number = Number.parseInt($('input[name="tmpText"]').val());
                            self.setSwimlaneWidth(number);
                        }
                    },
                    cancel: {
                        text: self.__Flowdesigner.getLang('static.cancel'),
                        btnClass: 'btn-primary'
                    }
                }
            });
        },
        setSwimlaneWidth: function (number) {
            var self = this;
            var width = number + Number.parseInt(self.laneShape[0].shape.points[0][1]);
            for (var i = 0; i < self.laneShape.length; i++) {
                var rectpoint = self.laneShape[i].shape.points;
                if (self.lanetype == 1) {
                    rectpoint[1][1] = width;
                    rectpoint[2][1] = width;
                } else {
                    rectpoint[2][0] = width;
                    rectpoint[3][0] = width;
                }
                self.laneShape[i].attr({
                    shape: {
                        points: rectpoint
                    }
                });
            }
            for (var i = 0; i < self.dragShape.length; i++) {
                var shape = self.dragShape[i].shape;
                if (self.lanetype == 1) {
                    shape.cy = (width + 1) / 2;
                } else {
                    shape.cx = (width + 1) / 2;
                }
                self.dragShape[i].attr({
                    shape: shape
                });
            }
            this.map['laneHeight'] = width;
        },
        _chgSwimlaneName: function (pos) {
            var self = this;
            // var pos = $.inArray(obj,this.textShape);
            $.confirm({
                title: self.__Flowdesigner.getLang('static.info'),
                content: self.__Flowdesigner.getLang('static.inputswimname')
                    + '<input type="text" value="' + self.lanename[pos] + '" name="tmpText">',
                type: 'blue',
                icon: 'glyphicon glyphicon-info-sign',
                buttons: {
                    ok: {
                        text: self.__Flowdesigner.getLang('static.ok'),
                        btnClass: 'btn-primary',
                        action: function () {
                            self.lanename[pos] = $('input[name="tmpText"]').val();
                            if (self.lanetype == 1) {
                                self.textShape[pos].attr({
                                    style: {
                                        text: self.lanename[pos]
                                    }
                                });
                            } else {
                                self._chgDrawText(self.textGroup[pos], self.lanename[pos]);
                            }
                        }
                    },
                    cancel: {
                        text: self.__Flowdesigner.getLang('static.cancel'),
                        btnClass: 'btn-primary'
                    }
                }
            });
        },
        //宽度改变
        _dragSwimlanePoint: function (ex, ey) {
            var point = this.laneShape[this.selPos].shape.points[0];
            var x = point[0], y = point[1];
            //重新计算宽度
            if (this.lanetype == 1) {
                this.lanewidth[this.selPos] = Math.max(ex - x, 60);
            } else {
                this.lanewidth[this.selPos] = Math.max(ey - y, 60);
            }

            this._refreshSwim(x, y, this.selPos);
        },
        //根据新的宽度,调整泳道
        _refreshSwim: function (x, y, startPos) {
            var pos = this.lanetype == 1 ? (x - 1) : (y - this.txtheight - 1);
            for (var i = startPos; i < this.lanenum; i++) {
                this.textShape[i].attr({
                    shape: this.lanetype == 1 ?
                        {
                            x: pos + 1,
                            width: this.lanewidth[i]
                        } :
                        {
                            y: pos + this.txtheight + 1,
                            height: this.lanewidth[i]
                        }
                });

                if (this.lanetype == 2) {
                    this.textGroup[i].cy = pos + this.txtheight + 1 + this.lanewidth[i] / 2;
                    this.textGroup[i].height = this.lanewidth[i];
                    this._chgDrawText(this.textGroup[i], this.lanename[i]);
                }

                var rectpoint = this._getRectPoints(pos, i);
                this.laneShape[i].attr({
                    shape: {
                        points: rectpoint
                    }
                });

                var shape = this._getDragPoint(rectpoint);

                this.dragShape[i].attr({
                    position: [0, 0],
                    shape: {
                        cx: shape.cx,
                        cy: shape.cy
                    }
                });
                pos += this.lanewidth[i];

                this.delLaneShape[i].attr({
                    style: {
                        x: shape.x,
                        y: shape.y
                    }
                });
            }

            this.cutWidth = pos;

            if (this.lanetype == 1) {
                this.titleShape.attr({
                    shape: {
                        width: pos
                    }
                });

                this.delTitleShape.attr({
                    style: {
                        x: pos / 2
                    }
                });
            }

            this.__drawLayer.checkSwimPoint();
            this.__drawLayer.refreshRect();
        },
        //更新map数据
        _reviewMap: function () {
            this.map.laneNum = this.lanenum;
            this.map.laneName = this.lanename;
            this.map.laneWidth = this.lanewidth;
        },
        addSelfToZr: function (init) {
            this.__drawLayer._swimlane = this;

            if (init == undefined) {
                this.map = {
                    id: this.id,
                    name: this.name,
                    laneType: this.lanetype
                };
                this._reviewMap();
                this._addSwimlaneToData();

                //对已有的节点进行坐标修正
                $.each(this.__drawLayer._nodes || [], function (id, node) {
                    node.moveNode();
                });

            }
            this.zrGroup = new zRender.Group();
            this.zrGroup.add(this.titleShape);
            for (var i = 0; i < this.lanenum; i++) {
                var tmpGroup = new zRender.Group();
                this.zrGroup.add(tmpGroup);
                this.laneGroup.push(tmpGroup);

                tmpGroup.add(this.textShape[i]);
                tmpGroup.add(this.laneShape[i]);
                if (this._showTypeisDesigner()) {
                    tmpGroup.add(this.dragShape[i]);
                }
                if (this.lanetype == 2) {
                    tmpGroup.add(this.textGroup[i]);
                }
            }

            this._addSwimlaneToLayer();

        },
        _showTypeisDesigner: function () {
            var showtype = this.__Flowdesigner.showtype;
            return showtype == 1 || showtype == 5;
        },
        _removeSelfFromZr: function () {
            this.__drawLayer.zrGroup.remove(this.zrGroup);
            this.__drawLayer._swimlane = null;
            delete this.__drawLayer.data.mapData['swimlane'];
        },

        _addSwimlaneToData: function () {
            this.__drawLayer.data.mapData.swimlane = this.map;
        },
        _addSwimlaneToLayer: function () {
            this.__drawLayer.zrGroup.add(this.zrGroup);
        },
        //画布大小改变
        zrResize: function () {
            var width = this.__Flowdesigner.zrender.getWidth() - this.txtheight - 25;
            var height = this.__Flowdesigner.zrender.getHeight() - 2 * this.txtheight - 25;
            var reDraw = false;
            if (width != this.maxWidth) {
                this.maxWidth = width;
                reDraw = true;
            }
            if (height != this.height) {
                this.maxHeight = height;
                reDraw = true;
            }
            if (reDraw) {
                if (this.lanetype == 2) {
                    this.titleShape.attr({
                        shape: {
                            width: width + this.txtheight
                        }
                    });
                }
                for (var i = 0; i < this.lanenum; i++) {
                    this.laneShape[i].attr({
                        shape: this.lanetype == 1 ?
                            {
                                height: height
                            } :
                            {
                                width: width
                            }
                    });
                }
            }
        },

        _deleteAllClick: function () {
            var self = this;
            var fd = self.__Flowdesigner;
            $.confirm({
                title: fd.getLang('static.warning'),
                content: fd.getLang('static.delswimlanes'),
                type: 'red',
                icon: 'glyphicon glyphicon-question-sign',
                buttons: {
                    ok: {
                        text: fd.getLang('static.ok'),
                        btnClass: 'btn-primary',
                        action: function () {
                            self._removeSelfFromZr();
                        }
                    },
                    cancel: {
                        text: fd.getLang('static.cancel'),
                        btnClass: 'btn-primary'
                    }
                }
            });
        },
        _deleteOneClick: function (pos) {
            var self = this;
            var fd = self.__Flowdesigner;
            $.confirm({
                title: fd.getLang('static.warning'),
                content: fd.getLang('static.delswimlane').replace('name', self.lanename[pos]),
                type: 'red',
                icon: 'glyphicon glyphicon-question-sign',
                buttons: {
                    ok: {
                        text: fd.getLang('static.ok'),
                        btnClass: 'btn-primary',
                        action: function () {
                            self._delOneLane(pos);
                        }
                    },
                    cancel: {
                        text: fd.getLang('static.cancel'),
                        btnClass: 'btn-primary'
                    }
                }
            });
        },

        _showContextMenu: function (param, pos) {
            var para = {};
            var self = this;
            var fd = this.__Flowdesigner;
            para.left = param.event.zrX;
            para.top = param.event.zrY;

            if (pos == null || pos == undefined) {
                //全部删除
                para.items = [
                    {
                        text: fd.getLang('menu.chgswim'),//'修改标题',
                        target: this,
                        fun: '_chgSwimlaneTitle',
                        para: null
                    },
                    {
                        text: '-',
                        enable: false
                    },
                    {
                        text: self.lanetype == 1 ? fd.getLang('menu.chgswimHeight') : fd.getLang('menu.chgswimWidth'),//'删除所有泳道',
                        target: this,
                        fun: '_chgSwimlaneWidth',
                        para: null
                    },
                    {
                        text: '-',
                        enable: false
                    },
                    {
                        text: fd.getLang('menu.delallswim'),//'删除所有泳道',
                        target: this,
                        fun: '_deleteAllClick',
                        para: null
                    }
                ];
            } else {
                para.items = [
                    {
                        text: fd.getLang('menu.chgswimname'),//'修改泳道名称',
                        target: this,
                        fun: '_chgSwimlaneName',
                        para: pos
                    },
                    {
                        text: '-',
                        enable: false
                    },
                    {
                        text: fd.getLang('menu.delswim'),//'删除此泳道',
                        target: this,
                        fun: '_deleteOneClick',
                        para: pos
                    }
                ];
            }
            para.event = param;
            para.layer = this.__drawLayer;
            this.__Flowdesigner.showContextMenu(para);
        }
    };
    return Swimlane;
});

/**
 * DOM模板
 */

define('flowdesigner/Template',['require'],function(require) {

	var templates = {};
	var chgHtml = {};
	var getLangVal = function(lang, langKey) {
		var val = lang;
		if(langKey.indexOf('.') != -1) {
			$.each(langKey.split('.'), function(i, _key) {
				val = val[_key];
			});
		}else {
			val = lang[langKey];
		}
		return val;
	};

	var formatLang = function(tls, lang) {
		if(!tls) return tls;
		var replaceArr = tls.match(/\<lang:\s*(\w+.)*\w+\s*\/>/g);
		if(replaceArr && replaceArr.length) {
			for(var i = 0, iLen = replaceArr.length; i < iLen; i++) {
				var langKey = replaceArr[i].replace('<lang:', '').replace('/>', '').trim();
				tls = tls.replace(replaceArr[i], getLangVal(lang, langKey));
			}
		}
		return tls;
	};

	var template = {
		put: function(key, value) {
			templates[key] = value;
		},
		get: function(key, lang) {
			var tls = chgHtml[key];//
			if(!tls){
				tls = templates[key];
				tls = lang ? formatLang(tls, lang): tls;
				chgHtml[key] = tls;
				delete templates[key];
			}
			return tls;
		}
	};

	template.put('template/container.html', '<div class="fd-container"><div class="fd-parts"><div class="fd-part-drag"></div></div><div class="fd-main"><div class="fd-canvas"></div></div></div>');
	template.put('template/flow/base.html', '<table border="0" style="width: 100%">    <tr>        <td style="width:100px;text-align:right"><lang:flow.base.flowid/></td>        <td style="width:80%">                <input type="text" class="form-control checkChange" name="flowId" value=""                                     placeholder="<lang:flow.base.idtip/>">            </div>        </td>    </tr>    <tr>        <td style="text-align: right"><lang:flow.base.flowname/></td>        <td><input type="text" class="form-control checkChange" name="flowName" maxlength="100"                   placeholder="<lang:flow.base.nametip/>"></td>    </tr>    <tr>        <td style="text-align: right"><lang:flow.base.type/></td>        <td>            <div class="form-inline">                <input type="text" class="form-control checkChange" name="flowType" maxlength="100"                       placeholder="<lang:flow.base.typetip/>" style="width:85%;" oninput="value=value.trim()">                <input type="hidden" name="flowTypeId" value="">                <input type="button" style="width:14%;" class="form-control btn btn-info" id="btnSelFlowType" value="<lang:flow.base.btnsel/>">            </div>        </td>    </tr>    <tr>        <td style="text-align: right"><lang:flow.base.limit/></td>        <td>            <div class="form-inline">                <input type="text" class="form-control checkChange" style="width: 100px"                       name="limitTime" placeholder="<lang:flow.base.inputnum/>">                <select class="form-control checkChange" name="limitType" style="width: 120px">                </select>                <span><lang:flow.base.limittip/></span>            </div>        </td>    </tr>    <tr>        <td style="text-align: right"><lang:flow.base.status/></td>        <td style="height: 34px">            <label class="radio-inline">                <input type="radio" class="checkChange" name="active" value="0" checked/><lang:flow.base.modify/>            </label>            <label class="radio-inline">                <input type="radio" class="checkChange" name="active" value="2"/><lang:flow.base.test/>            </label>            <label class="radio-inline">                <input type="radio" class="checkChange" name="active" value="1"/><lang:flow.base.pub/>            </label>        </td>    </tr>    <tr>        <td style="text-align: right"></td>        <td style="height: 34px">            <label class="checkbox-inline"><input type="checkbox" class="checkChange" name="updateToDB" value="true"/><lang:flow.base.sync/></label>        </td>    </tr>    <tr>        <td style="text-align:right;vertical-align: top"><lang:flow.base.memo/></td>        <td>            <textarea class="form-control input-sm checkChange" style="resize:none"  rows="7" name="memo" maxlength="1000"/>        </td>    </tr></table>');
	template.put('template/flow/form.html', '<div class="panel-group chgPanel-group">    <table id="tblFlowForm">    </table>    <div class="panel panel-white" style="height: 35px;margin-top:5px">            <div class="btn-group pull-left">                <button type="button" class="btn btn-info btn-sm" id="btnAddForm"><lang:flow.form.btnAdd/></button>                <button type="button" class="btn btn-info btn-sm" id="btnRplForm"><lang:flow.form.btnReplace/></button>                <button type="button" class="btn btn-default btn-sm" id="btnAddTrack"><lang:flow.form.btnTrack/></button>            </div>            <div class="btn-group pull-right">                <button type="button" class="btn btn-info btn-sm" id="btnUp"><lang:flow.form.btnUp/></button>                <button type="button" class="btn btn-info btn-sm" id="btnDown"><lang:flow.form.btnDown/></button>                <button type="button" class="btn btn-danger btn-sm" id="btnDelForm"><lang:flow.form.btnDel/></button>                <button type="button" class="btn btn-danger btn-sm" id="btnDelFormAll"><lang:flow.form.btnDelAll/></button>            </div>    </div>    <div class="panel panel-white"  style="height: 45px;">            <label ><lang:flow.form.msg1/></label><br/>            <label ><lang:flow.form.msg2/></label>    </div>    <div class="panel panel-white" >        <table border="0">            <tr>                <td><lang:flow.form.main/></td>                <td><select  id="selectMainForm" class="form-control input-sm checkChange" style="width:300px">                </select></td>            </tr>        </table>    </div></div>');
	template.put('template/flow/reader.html', '<div><ul class="nav nav-tabs" role="tablist"><li role="presentation"  class="active"><a href="#reader" aria-controls="reader" role="tab" data-toggle="tab"><lang:flow.participant.reader/></a></li></ul><div class="tab-content"><div role="tabpanel" class="tab-pane active hzSecondTab tabSecondFlow" id="reader"><table id="tblUserOrg"></table><div class="btn-group pull-right" style="margin-top:5px;margin-bottom:5px"><button type="button" class="btn btn-info btn-sm" id="btnOrgAdd"><lang:flow.participant.btnAdd/></button><button type="button" class="btn btn-danger btn-sm" id="btnOrgDel"><lang:flow.participant.btnDel/></button><button type="button" class="btn btn-danger btn-sm" id="btnOrgDelAll"><lang:flow.participant.btnDelAll/></button></div></div></div></div>');
	template.put('template/flow/senior.html', '<div class="form-group"><label class="control-label"><lang:flow.senior.msg1/></label><div><select class="form-control input-sm checkChange" name="openTodoFlag"><option value="1"><lang:flow.senior.open1/></option><option value="0"><lang:flow.senior.open2/></option></select></div></div><div class="form-group"><label class="control-label"><lang:flow.senior.msg2/></label><div><input class="form-control input-sm checkChange" name="startRuleClassName" value="com.horizon.wf.rule.defa.StartRuleDefault"></input></div></div><div class="form-group"><label class="control-label"><lang:flow.senior.msg3/></label><div><input class="form-control input-sm checkChange" name="checkRoleClassName" value="com.horizon.wf.rule.defa.CheckRoleForOpenInstanceDefault"></input></div></div><div class="form-group"><label class="control-label"><lang:flow.senior.msg4/></label><div><input class="form-control input-sm checkChange" name="trackLogClassName" value="com.horizon.wf.rule.defa.TrackLogDefault"></input></div></div><div class="form-group"><label class="control-label"><lang:flow.senior.msg5/></label><div><input class="form-control input-sm checkChange" name="relationRuleClassName" value="com.horizon.wf.rule.defa.RelationRuleDefault"></input></div></div>');
	template.put('template/flow/variable.html', '<div class="chgPanel-group">    <table id="tblFlowVar"></table>    <div class="panel panel-white" style="margin-top:5px;margin-bottom:5px">        <button type="button" class="btn btn-danger btn-sm" id="btnVarDel"><lang:flow.var.btnDel/></button>        <button type="button" class="btn btn-danger btn-sm" id="btnVarDelAll"><lang:flow.var.btnDelAll/></button>        <button type="button" class="btn btn-info btn-sm pull-right" id="btnVarAdd"><lang:flow.var.btnAdd/></button>    </div>    <div class="panel panel-white">        <table border="0" style="width: 100%">            <tr>                <td style="width:80px;text-align:right"></td>                <td style="width:150px;text-align:left"></td>                <td style="width:80px;text-align:right"></td>                <td style="width:150px;text-align:left"></td>            </tr>            <tr>                <td style="text-align:right"><lang:flow.var.id/></td>                <td><input class="form-control input-sm" name="varId" value=""/></td>                <td style="text-align:right"><lang:flow.var.name/></td>                <td><input class="form-control input-sm" name="varName" value=""/></td>            </tr>            <tr>                <td style="text-align:right"><lang:flow.var.type/></td>                <td><select class="form-control input-sm" name="varType">                </select></td>                <td style="text-align:right"><lang:flow.var.length/></td>                <td><input class="form-control input-sm" name="varLen" value="1"/></td>            </tr>            <tr>                <td style="text-align:right"><lang:flow.var.default/></td>                <td><input class="form-control input-sm" name="initValue" value=""/></td>                <td style="text-align:right"><lang:flow.var.memo/></td>                <td><input class="form-control input-sm" name="memo" value=""/></td>            </tr>            <tr>                <td style="text-align:right"><lang:flow.var.from/></td>                <td colspan="2"><select name="formlst" class="form-control input-sm " >                </select></td>                <td ><select  name="fieldlst" class="form-control input-sm " >                </select></td>            </tr>        </table>    </div></div>');
	template.put('template/flow.html', '<div>    <div>        <ul class="nav nav-tabs tblNavBG" role="tablist">            <li role="presentation"  class="active">                <a href="#base" aria-controls="base" role="tab" data-toggle="tab"><lang:flow.base.title/></a>            </li>            <li role="presentation" >                <a href="#form" aria-controls="form" role="tab" data-toggle="tab"><lang:flow.form.title/></a>            </li>            <li role="presentation">                <a href="#var" aria-controls="var" role="tab" data-toggle="tab"><lang:flow.var.title/></a>            </li>            <li role="presentation">                <a href="#participant" aria-controls="participant" role="tab" data-toggle="tab"><lang:flow.participant.title/></a>            </li>            <li role="presentation">                <a href="#senior" aria-controls="senior" role="tab" data-toggle="tab"><lang:flow.senior.title/></a>            </li>        </ul>        <div class="tab-content">            <div role="tabpanel" class="tab-pane hzTab tabFlow active" id="base">            </div>            <div role="tabpanel" class="tab-pane hzTab tabFlow" id="form">            </div>            <div role="tabpanel" class="tab-pane hzTab tabFlow" id="var">            </div>            <div role="tabpanel" class="tab-pane hzTab tabFlow" id="participant">            </div>            <div role="tabpanel" class="tab-pane hzTab tabFlow" id="senior">            </div>        </div>    </div></div>');
	template.put('template/footer1.html', '<button type="button" class="btn btn-primary" id="okBtn"><lang:popwin.ok/></button><button type="button" class="btn btn-default" data-dismiss="modal"><lang:popwin.cancel/></button><button type="button" class="btn btn-info" id="applyBtn" disabled="disabled"><lang:popwin.apply/></button>');
	template.put('template/footer2.html', '<button type="button" class="btn btn-info" id="selBtn"><lang:popwin.sel/></button><button type="button" class="btn btn-info" id="okBtn"><lang:popwin.import/></button><button type="button" class="btn btn-info" id="delBtn"><lang:popwin.del/></button><button type="button" class="btn btn-default" data-dismiss="modal"><lang:popwin.close/></button>');
	template.put('template/node/actionform/fieldEdit.html', '<div style="width:650px;height: 30px">    ID:&nbsp;&nbsp;<input type="text" name="authId" disabled style="width:273px;height: 27px">    <lang:node.action.a3/>&nbsp;&nbsp;<input type="text" name="authName" style="width:230px;height: 27px"></div><div style="width:650px;">    <ul class="nav nav-tabs" role="tablist">        <li role="presentation" class="pc" style="display: none">            <a href="#pc" aria-controls="pc" role="tab" data-toggle="tab">                <lang:form.clientType.a1/>            </a>        </li>        <li role="presentation" class="pad" style="display: none">            <a href="#pad" aria-controls="pad" role="tab" data-toggle="tab">                <lang:form.clientType.a2/>            </a>        </li>        <li role="presentation" class="phone" style="display: none">            <a href="#phone" aria-controls="phone" role="tab" data-toggle="tab">                <lang:form.clientType.a3/>            </a>        </li>    </ul>    <div class="tab-content" style="height: 200px;">        <div role="tabpanel" class="tab-pane hzSecondTab tabSecondFlow" id="pc" style="width: 650px;height: 100%;">            <table id="pc-popSel"></table>        </div>        <div role="tabpanel" class="tab-pane hzSecondTab tabSecondFlow" id="notebook" style="width: 650px;height: 100%;">            <table id="notebook-popSel"></table>        </div>        <div role="tabpanel" class="tab-pane hzSecondTab tabSecondFlow" id="pad" style="width: 650px;height: 100%;">            <table id="pad-popSel"></table>        </div>        <div role="tabpanel" class="tab-pane hzSecondTab tabSecondFlow" id="phone" style="width: 650px;height: 100%;">            <table id="phone-popSel"></table>        </div>    </div></div><!--    <div class="tabFieldEdit" style="margin-top: 35px;">--><!--        <div class="form-inline" style="margin-left: 10px;margin-top: 5px;height: 245px">--><!--            <lang:node.action.a4/>--><!--            <br>--><!--            <label class="radio-inline ">--><!--                <input type="radio" name="applyTo" value="edit"/>--><!--                <lang:node.action.a5/>--><!--            </label><br>--><!--            <label class="checkbox-inline ">--><!--                <input type="checkbox" name="must" value="1"/>--><!--                <lang:node.action.a6/>--><!--            </label><br>--><!--            <label class="radio-inline ">--><!--                <input type="radio" name="applyTo" value="read"/>--><!--                <lang:node.action.a7/>--><!--            </label><br>--><!--            <label class="radio-inline ">--><!--                <input type="radio" name="applyTo" value="hide"/>--><!--                <lang:node.action.a8/>--><!--            </label><br>--><!--            <button type="button" class="btn btn-info btn-sm" id="btnApply">--><!--                <lang:node.action.a9/>--><!--            </button>--><!--        </div>--><!--    </div>-->');
	template.put('template/node/actionform/nodeAction.html', '<div style="width:695px">    <table id="tblAction"></table></div><div class="tabOperatorPro">    <div class="form-inline" style="margin-left: 10px;margin-top: 5px;height: 225px">        <lang:node.action.a10/><br>        <label class="checkbox-inline " style="display: none">            <input type="checkbox" name="rejectOther" value="1"  class="checkChange" />            <lang:node.action.a11/>        </label>        <br>        <label class="input-group">            <lang:node.action.a111/><br>            <select name="rejectNodes" style="width:175px;height:95px" size="15"/>        </label>        <label class="input-group">            <lang:node.action.a12/><br>            <select name="backNodes" style="width:175px;height:95px" size="15"/>        </label>    </div>    <div class="form-inline" style="margin-left: 10px;;margin-bottom: 5px">        <button type="button" class="btn btn-info btn-sm" id="btnCopyToOter"><lang:node.action.a13/></button>    </div></div>');
	template.put('template/node/actionform/nodeForm.html', '<table id="tblForm"></table><div class="from-inline" style="margin-top: 5px">    <lang:node.action.a14/>&nbsp;&nbsp;<select  name="defForm" style="width:200px" class="checkChange"></select>    <div class="btn-group pull-right">        <label class="checkbox-inline">            <input type="checkbox" name="chgForm" value="1"  class="checkChange" />            <lang:node.action.a15/>        </label>        <button type="button" class="btn btn-info btn-sm" id="btnUp" disabled><lang:node.action.a16/></button>        <button type="button" class="btn btn-info btn-sm" id="btnDown" disabled><lang:node.action.a17/></button>    </div></div>');
	template.put('template/node/actionform.html', '<div>    <ul class="nav nav-tabs tblNavBG" role="tablist">        <li role="presentation" class="active">            <a href="#nodeAction" aria-controls="nodeAction" role="tab" data-toggle="tab"><lang:node.action.a1/></a>        </li>        <li role="presentation">            <a href="#nodeForm" aria-controls="nodeForm" role="tab" data-toggle="tab"><lang:node.action.a2/></a>        </li>    </ul>    <div class="tab-content">        <div role="tabpanel" class="tab-pane active hzSecondTab tabAction"  id="nodeAction">        </div>        <div role="tabpanel" class="tab-pane hzSecondTab tabAction" id="nodeForm">        </div>    </div></div>');
	template.put('template/node/base/end.html', '<div role="tabpanel" class="tab-pane hzNodeBase Node_End Node_End_Instance">    <div class="form-inline" style="margin-left: 30px;">        <table style="border: 1px #ddd solid;width: 800px;">            <tr>                <td height="10px"></td>            </tr>            <tr>                <td width="30px"></td>                <td>                    <lang:node.base.end1/>                    <button type="button" class="btn-link btnExample">                        <lang:example/>                    </button>                </td>            </tr>            <tr>                <td></td>                <td>                    <input type="text" name="entryClassName" class="checkChange hzRadioInput" style="width:740px"/>                </td>            </tr>            <tr>                <td></td>                <td>                    <lang:node.base.end2/>&nbsp;&nbsp;<button type="button" id="btnEditEntryRule"                                                              class="btn btn-info btn-sm">                    <lang:node.base.end3/>                </button>                </td>            </tr>            <tr>                <td></td>                <td>                    <textarea name="entryRuleText" class="form-control input-sm checkChange"                              style="width:740px;resize:none" rows="5"></textarea>                    <textarea name="entryRuleScript" style="display: none"></textarea>                    <input type="hidden" name="entryRuleId"/>                </td>            </tr>            <tr>                <td height="10px"></td>            </tr>        </table>    </div></div>');
	template.put('template/node/base/event.html', '<div role="tabpanel" class="tab-pane hzNodeBase Node_Event_Intermediate">    <div class="form-inline" style="margin-left: 40px;">        <table style="border: 1px #ddd solid;width: 800px;">            <tr>                <td width="30px"></td>                <td>                    <span><lang:node.base.e1/><button type="button" class="btn-link btnExample"><lang:example/></button></span>                </td>            </tr>            <tr>                <td width="30px"></td>                <td>                    <input type="text" name="eventClassName" style="width:530px" class="checkChange hzRadioInput"/>                </td>            </tr>            <tr>                <td height="10px"></td>            </tr>        </table>    </div></div><div role="tabpanel" class="tab-pane hzNodeBase Node_Event_Timer">    <div class="form-inline" style="margin-left: 40px;">        <table style="border: 1px #ddd solid;width: 800px;">            <tr>                <td height="10px"></td>            </tr>            <tr>                <td width="30px"></td>                <td>                    <span><lang:node.base.e2/>&nbsp;&nbsp;</span>                    <select name="timeDate" class="checkChange hzRadioInput" style="width:150px;"></select>                    <span>&nbsp;&nbsp;<lang:node.base.e3/></span>                </td>            </tr>            <tr>                <td width="30px"></td>                <td>                    <label class="checkbox-inline">                        <input type="checkbox" class="checkChange " name="timeRetry" value="1"/>                        <lang:node.base.e4/>                    </label>                </td>            </tr>            <tr>                <td width="30px"></td>                <td>                    <span><lang:node.base.e5/>&nbsp;&nbsp;</span>                    <input type="number" name="timeCycle" max="2147483647" class="checkChange hzRadioInput" disabled="true" value="1000"                           style="width:110px" onblur="this.value=this.value>2147483647?2147483647:this.value">                    <span><lang:node.base.e6/></span>                </td>            </tr>            <tr>                <td width="30px"></td>                <td>                    <span><lang:node.base.e7/>&nbsp;&nbsp;</span>                    <input type="number" name="num" max="2147483647" class="checkChange hzRadioInput" disabled="true" value="0"                           style="width:110px" onblur="this.value=this.value>2147483647?2147483647:this.value">                    <span><lang:node.base.e8/></span>                </td>            </tr>            <tr>                <td width="30px"></td>                <td>                    <span><lang:node.base.e9/><button type="button" class="btn-link btnExample"><lang:example/></button></span>                    <input type="text" name="timeClassName" style="width:530px" class="checkChange hzRadioInput"/>                </td>            </tr>            <tr>                <td height="10px"></td>            </tr>        </table>    </div></div><div role="tabpanel" class="tab-pane hzNodeBase Node_Event_Message">    <div class="form-inline" style="margin-left: 30px;">        <table style="border: 1px #ddd solid;width: 800px;">            <tr>                <td height="10px"></td>            </tr>            <tr>                <td width="30px"></td>                <td width="100px" style="text-align: right">                    <lang:node.base.e10/>                </td>                <td width="200px">                    <select name="msgType" style="width: 250px;" class="hzRadioInput">                        <option value="2">JMS</option>                    </select>                </td>            </tr>            <tr>                <td width="30px"></td>                <td style="text-align: right">                    <lang:node.base.e11/>                </td>                <td><input type="text" name="msgId" style="width: 250px" class="checkChange hzRadioInput"></td>                <td style="text-align: right">                    <lang:node.base.e12/>                </td>                <td><input type="text" name="msgName" style="width: 200px" class="checkChange hzRadioInput"></td>                <td></td>            </tr>            <tr>                <td width="30px"></td>                <td style="text-align: right">                    <lang:node.base.e13/>                </td>                <td><input type="text" name="msgFrom" style="width: 250px" class="checkChange hzRadioInput"></td>                <td style="text-align: right">                    <lang:node.base.e14/>                </td>                <td><input type="text" name="msgTo" style="width: 200px" class="checkChange hzRadioInput"></td>                <td></td>            </tr>            <tr>                <td width="30px"></td>                <td style="text-align: right" width="120px">                    <lang:node.base.e16/>                </td>                <td width="250px">                    <input type="text" name="msgClass" class="checkChange hzRadioInput" style="width: 250px">                </td>                <td style="text-align: right">                    <lang:node.base.e15/>                </td>                <td><select name="msgPara" style="width: 200px" class="checkChange hzRadioInput"></select></td>            </tr>            <tr>                <td width="30px"></td>                <td></td>                <td colspan="4"><span><lang:node.base.e17/><button type="button" class="btn-link btnExample"><lang:example/></button></span>                </td>            </tr>        </table>    </div></div><div role="tabpanel" class="tab-pane hzNodeBase Node_Event_Signal_Throw Node_Event_Signal_Catch">    <div class="form-inline" style="margin-left: 30px;">        <table style="border: 1px #ddd solid;width: 800px;">        <tr>            <td width="30px" height="10px"></td>        </tr>            <tr>                <td></td>                <td>                    <span><lang:node.base.e18/></span>                    <select name="signalPara" style="width: 200px" class="checkChange"></select>                </td>            </tr>            <tr>                <td></td>                <td>                    <span><lang:node.base.e19/><button type="button" class="btn-link btnExample"><lang:example/></button></span>                </td>            </tr>            <tr>                <td></td>                <td>                    <input type="text" name="signalClass" style="width:530px" class="checkChange hzRadioInput"/>                </td>            </tr>            <tr>                <td height="10px"></td>            </tr>        </table>    </div></div>');
	template.put('template/node/base/gateway.html', '<div role="tabpanel" class="tab-pane hzNodeBase Node_GateWay_Merge">    <div class="form-inline" style="margin-left: 30px;">        <table style="border: 1px #ddd solid;width: 800px;">            <tr>                <td style="font-weight: 600;" colspan="2"><lang:node.base.g1/></td>            </tr>            <tr>                <td width="30px"></td>                <td colspan="2">                <label class="checkbox-inline">                    <input type="checkbox" name="cancelOther" class="checkChange"  value="1"/>                    <lang:node.base.g2/>                </label>                <label class="checkbox-inline">                    <input type="checkbox" name="submitAgain" class="checkChange"  value="1"/>                    <lang:node.base.g3/>                </label>            </td></tr>            <tr>                <td width="30px"></td>                <td colspan="2"><lang:node.base.g4/>                    <input type="text" name="mergerClassName" class="checkChange input-sm" style="width:350px"/>                </td>            </tr>            <tr>                <td width="30px"></td>                <td style="color:red"><lang:node.base.g41/>                </td>                <td>                    &nbsp;<button type="button" class="btn-link pull-right btnExample" ><lang:example/></button>                </td>            </tr>            <tr>                <td width="30px"></td>                <td><lang:node.base.g5/>&nbsp;&nbsp;                    <button type="button" id="btnEditMergerRule" class="btn btn-info btn-sm"><lang:node.base.g6/></button>                </td>            </tr>            <tr>                <td width="30px"></td>                <td colspan="2">                    <textarea name="mergerRuleText" class="form-control input-sm checkChange" style="width:100%;resize:none" rows="5"></textarea>                    <textarea name="mergerRuleScript" style="display: none"></textarea>                    <input type="hidden" name="mergerRuleId"/>                </td>            </tr>            <tr>                <td height="10px"></td>            </tr>        </table>    </div></div><div role="tabpanel" class="tab-pane hzNodeBase Node_GateWay_Split">    <div class="form-inline" style="margin-left: 30px;">        <table style="border: 1px #ddd solid;width: 800px;">            <tr>                <td height="10px"></td>            </tr>            <tr>                <td width="30px"></td>                <td>                    <span><lang:node.base.g7/><button type="button" class="btn-link btnExample" ><lang:example/></button></span>                </td>            </tr>            <tr>                <td width="30px"></td>                <td>                    <input type="text" name="splitClassName" class="checkChange input-sm"  style="width:740px"/>                </td>            </tr>            <tr>                <td height="10px"></td>            </tr>        </table>    </div></div>');
	template.put('template/node/base/normal.html', '<div role="tabpanel" class="tab-pane hzNodeBase Node_Multi">    <div class="form-inline" style="margin-left: 40px;">        <table style="border: 1px #ddd solid;width: 800px;">            <tr>                <td colspan="2">                    <span style="font-weight: 600"><lang:node.base.n1/></span>                </td>            </tr>            <tr>                <td width="30px"></td>                <td>                    <label class="radio-inline ">                        <input type="radio" class="checkChange" name="passType" value="1"/>                        <lang:node.base.n2/>                        <input type="text" name="passPara1" style="width:40px" class="hzRadioInput" value="1">                        <lang:node.base.n3/>                    </label>                </td>            </tr>            <tr>                <td width="30px"></td>                <td>                    <label class="radio-inline ">                        <input type="radio" class="checkChange" name="passType" value="2"/>                        <lang:node.base.n4/>                        <input type="text" name="passPara2" class="hzRadioInput" style="width:400px" readonly>                    </label>                </td>            </tr>            <tr>                <td width="30px"></td>                <td>                    <label class="radio-inline ">                        <input type="radio" class="checkChange" name="passType" value="3"/>                        <lang:node.base.n5/>                        <input type="text" name="passPara3" class="hzRadioInput" style="width:400px" readonly>                    </label>                </td>            </tr>            <tr>                <td width="30px"></td>                <td>                    <label class="radio-inline ">                        <input type="radio" class="checkChange" name="passType" value="4"/>                        <lang:node.base.n6/>                        <input type="text" name="passPara4" style="width:40px" class="hzRadioInput" value="100">                        <lang:node.base.n7/>                    </label>                </td>            </tr>            <tr>                <td width="30px"></td>                <td>                    <label class="radio-inline ">                        <input type="radio" class="checkChange" name="passType" value="5"/>                        <lang:node.base.n8/>                        <input type="text" name="passPara5" class="hzRadioInput" style="width:285px">                    </label>                </td>            </tr>            <tr>                <td width="30px"></td>                <td>                    <button type="button" class="btn-link pull-right btnExample">                        <lang:example/>                    </button>                </td>            </tr>        </table>    </div></div><div role="tabpanel" class="tab-pane hzNodeBase Node_Merger">    <div class="form-inline" style="margin-left: 40px;">        <table style="border: 1px #ddd solid;width: 800px;">            <tr>                <td colspan="2" style="width:180px;font-weight: 600">                    <lang:node.base.m1/>                </td>                <td style="width:400px;text-align: right;">                    <label class="checkbox-inline">                        <input type="checkbox" name="cancelOther" value="1" class="checkChange"/>                        <lang:node.base.m2/>                    </label>                </td>            </tr>            <tr>                <td style="width: 30px;"></td>                <td colspan="2">                    <label class="radio-inline ">                        <input type="radio" class="checkChange"                               name="activeType" value="5"/>                        <lang:node.base.m3/>                    </label>                </td>            </tr>            <tr>                <td></td>                <td colspan="2">                    <label class="radio-inline ">                        <input type="radio" class="checkChange" checked                               name="activeType" value="4"/>                        <lang:node.base.m4/>                    </label>                </td>            </tr>            <tr>                <td></td>                <td colspan="2">                    <label class="radio-inline ">                        <input type="radio" class="checkChange" name="activeType" value="1"/>                        <lang:node.base.m5/>                        <input type="text" name="activePara1" class="hzRadioInput" style="width:30px" value="1">                        <lang:node.base.m6/>                    </label>                </td>            </tr>            <tr>                <td></td>                <td colspan="2">                    <label class="radio-inline ">                        <input type="radio" class="checkChange" name="activeType" value="2"/>                        <lang:node.base.m7/>                        <input type="text" name="activePara2" readonly class="hzRadioInput" style="width:200px">                    </label>                </td>            </tr>            <tr>                <td></td>                <td colspan="2">                    <label class="radio-inline ">                        <input type="radio" class="checkChange" name="activeType" value="3"/>                        <lang:node.base.m8/>                        <input type="text" name="activePara3" readonly class="hzRadioInput" style="width:200px">                    </label>                </td>            </tr>            <tr>                <td></td>                <td colspan="2">                    <label class="radio-inline ">                        <input type="radio" class="checkChange" name="activeType" value="6"/>                        <lang:node.base.m9/>                        <input type="text" name="activePara6" class="hzRadioInput" style="width:260px">                    </label>                </td>            </tr>            <tr>                <td colspan="3">                    <span class="form-inline" style="margin-left: 50px"><lang:node.base.me2/><button type="button" class="btn-link btnExample"><lang:example/></button></span>                </td>            </tr>        </table>        <div style="width: 780px; text-align: center;min-height: 5px;">            <!--            <img style="display: initial" width="30" src="./src/assets/img/part1/down.png">-->            <!--            <div style="display: inline-block;width: 100px"></div>-->            <!--            <img style="display: initial" width="30" src="./src/assets/img/part1/down.png">-->        </div>        <table style="border: 1px #ddd solid;width: 800px;">            <tr>                <td style="width:180px;font-weight: 600" colspan="2">                    <lang:node.base.l1/>                </td>                <td style="width:600px;text-align: right;">                    <label class="checkbox-inline">                        <input type="checkbox" name="submitAgain" class="checkChange" value="1"/>                        <lang:node.base.l2/>                    </label>                    <label class="checkbox-inline">                        <input type="checkbox" name="leaveCancel" value="1" class="checkChange"/>                        <lang:node.base.l22/>                    </label>                </td>            </tr>            <tr>                <td style="width: 30px;"></td>                <td style="width:140px">                    <label class="radio-inline ">                        <input type="radio" class="checkChange"                               name="leaveType" value="5"/>                        <lang:node.base.l3/>                    </label>                </td>            </tr>            <tr>                <td></td>                <td colspan="2">                    <label class="radio-inline ">                        <input type="radio" class="checkChange" checked                               name="leaveType" value="4"/>                        <lang:node.base.l4/>                    </label>                </td>            </tr>            <tr>                <td></td>                <td colspan="2">                    <label class="radio-inline ">                        <input type="radio" class="checkChange" name="leaveType" value="1"/>                        <lang:node.base.l5/>                        <input type="text" name="leavePara1" value="1" class="hzRadioInput" style="width:30px">                        <lang:node.base.l6/>                    </label>                </td>            </tr>            <tr>                <td></td>                <td colspan="2">                    <label class="radio-inline ">                        <input type="radio" class="checkChange" name="leaveType" value="2"/>                        <lang:node.base.l7/>                        <input type="text" name="leavePara2" readonly class="hzRadioInput" style="width:175px">                    </label>                </td>            </tr>            <tr>                <td></td>                <td colspan="2">                    <label class="radio-inline ">                        <input type="radio" class="checkChange" name="leaveType" value="3"/>                        <lang:node.base.l8/>                        <input type="text" name="leavePara3" readonly class="hzRadioInput" style="width:175px">                    </label>                </td>            </tr>            <tr>                <td></td>                <td colspan="2">                    <label class="radio-inline ">                        <input type="radio" class="checkChange" name="leaveType" value="6"/>                        <lang:node.base.l9/>                        <input type="text" name="leavePara6" class="hzRadioInput" style="width:260px">                    </label>                </td>            </tr>            <tr>                <td colspan="3">                    <span class="form-inline" style="margin-left: 50px"><lang:node.base.me4/><button type="button" class="btn-link btnExample"><lang:example/></button></span>                </td>            </tr>        </table>        <label class="checkbox-inline" style="margin-top: 10px;">            <input type="checkbox" class="checkChange" name="reSelect" value="1" disabled="true"/>            <lang:node.base.me1/>        </label>    </div></div><div role="tabpanel" class="tab-pane hzNodeBase Node_Progressively">    <div class="form-inline" style="margin-left: 40px;">        <table style="border: 1px #ddd solid;width: 800px;">            <tr>                <td style="height:10px;width: 30px;"></td>                <td></td>            </tr>            <tr>                <td width="30px"></td>                <td>                    <span><lang:node.base.me3/><button type="button" class="btn-link btnExample"><lang:example/></button></span>                </td>            </tr>            <tr>                <td width="30px"></td>                <td>                    <input type="text" class="checkChange" name="progressivelyClassName" style="width:530px"/>                </td>            </tr>            <tr>                <td style="height:10px;width: 30px;"></td>                <td></td>            </tr>        </table>    </div></div>');
	template.put('template/node/base/robot.html', '<div role="tabpanel" class="tab-pane hzNodeBase Node_Auto_Program">    <div class="form-inline" style="margin-left: 30px;">        <table style="border: 1px #ddd solid;width: 800px;">            <tr>                <td height="10px"></td>            </tr>            <tr>                <td width="30px"></td>                <td>                    <span><lang:node.base.r/><button type="button" class="btn-link btnExample" ><lang:example/></button></span>                </td>            </tr>            <tr>                <td width="30px"></td>                <td>                    <input type="text" name="robotClassName" class="checkChange"  style="width:740px"/>                </td>            </tr>            <tr>                <td height="10px"></td>            </tr>        </table>    </div></div>');
	template.put('template/node/base/start.html', '<div role="tabpanel" class="tab-pane hzNodeBase Node_Timer_Start">    <div class="form-inline" style="margin-left: 30px;">        <table style="border: 1px #ddd solid;width: 800px;">            <tr>                <td height="10px"></td>            </tr>            <tr>                <td width="30px"></td>                <td>                    <span><lang:node.base.s1/></span>                </td>                <td>                    <input type="datetime" name="timeDate" class="checkChange hzRadioInput" style="width:350px;">                </td>            </tr>            <tr>                <td></td>                <td>                    <span><lang:node.base.s2/></span>                </td>                <td>                    <input type="text" name="timeCycle" class="checkChange hzRadioInput" style="width:350px" value="0">                </td>            </tr>            <tr>                <td></td>                <td></td>                <td>                    <span><lang:node.base.s3/></span>                </td>            </tr>            <tr>                <td height="10px"></td>            </tr>        </table>    </div></div><div role="tabpanel" class="tab-pane hzNodeBase Node_Signal_Start">    <div class="form-inline" style="margin-left: 30px;">        <table style="border: 1px #ddd solid;width: 800px;">            <tr>                <td height="10px"></td>            </tr>            <tr>                <td width="30px"></td>                <td>                    <span><lang:node.base.s4/></span>                </td>                <td>                    <input name="signalPara" style="width: 350px" class="checkChange"/>                </td>            </tr>            <tr>                <td height="10px" h></td>            </tr>        </table>    </div></div><div role="tabpanel" class="tab-pane hzNodeBase Node_Msg_Start">    <div class="form-inline" style="margin-left: 30px;">        <table style="border: 1px #ddd solid;width: 800px;">            <tr>                <td height="10px"></td>            </tr>            <tr>                <td width="30px"></td>                <td style="text-align: right">                    <lang:node.base.s5/>                </td>                <td>                    <select name="msgType" style="width: 200px">                        <option value="2">JMS</option>                    </select>                </td>                <td style="text-align: right">                    <lang:node.base.s6/>                </td>                <td><input type="text" name="msgPara" style="width: 200px" class="checkChange"/></td>            </tr>            <tr>                <td></td>                <td style="text-align: right">                    <lang:node.base.s7/>                </td>                <td><input type="text" name="msgId" style="width: 200px" class="checkChange"></td>                <td style="text-align: right">                    <lang:node.base.s8/>                </td>                <td><input type="text" name="msgName" style="width: 200px" class="checkChange"></td>            </tr>            <tr>                <td></td>                <td style="text-align: right">                    <lang:node.base.s9/>                </td>                <td><input type="text" name="msgFrom" style="width: 200px" class="checkChange"></td>                <td style="text-align: right">                    <lang:node.base.s10/>                </td>                <td><input type="text" name="msgTo" style="width: 200px" class="checkChange"></td>            </tr>            <tr>                <td height="10px"></td>            </tr>        </table>    </div></div>');
	template.put('template/node/base.html', '<table border="0" style="width: 100%">    <tr>        <td style="text-align:right">            <lang:node.base.id/>        </td>        <td><input type="text" class="form-control checkChange" name="nodeId" readonly></td>        <td style="text-align:right">            <lang:node.base.name/>        </td>        <td><input type="text" class="form-control checkChange" name="nodeName"                   placeholder="<lang:node.base.tip/>"></td>        <td colspan="2">            <div class="form-inline" id="divNxtSelType">                <lang:node.base.sel/>                <label class="radio-inline hidepage Node_Normal">                    <input type="radio" class="checkChange" name="nxtSelType" value="0"/>                    <lang:node.base.sel1/>                </label>                <label class="radio-inline">                    <input type="radio" class="checkChange" name="nxtSelType" value="1"/>                    <lang:node.base.sel2/>                </label>                <label class="radio-inline">                    <input type="radio" class="checkChange" name="nxtSelType" value="2" checked/>                    <lang:node.base.sel3/>                </label>            </div>        </td>    </tr>    <tr>        <td style="text-align:right" id="tdNodeType">            <lang:node.base.type/>        </td>        <td><select class="form-control checkChange" name="nodeType"></select></td>        <td colspan="4">            <label class="checkbox-inline hidepage Node_Multi_Single">                <input type="checkbox" class="checkChange" name="grab" value="1"/>                <lang:node.base.ck1/>            </label>            <label class="checkbox-inline hidepage Node_Multi">                <input type="checkbox" class="checkChange" name="asyn" value="1"/>                <lang:node.base.ck2/>            </label>            <label class="checkbox-inline hidepage Node_Multi">                <input type="checkbox" class="checkChange" name="lock" value="1"/>                <lang:node.base.ck3/>            </label>            <label class="checkbox-inline hidepage Node_Merger">                <input type="checkbox" class="checkChange" name="mergerAll" value="1"/>                <lang:node.base.ck4/>            </label>        </td>    </tr>    <tr style="font-size: 12px;">        <td></td>        </td>        <td colspan="5">            <span style="color:red" id="nodetype_title"></span>        </td>    </tr>    <tr style="width:100%;height: 110px;max-height: 240px">        <td colspan="5">            <div id="idSpecial">            </div>        </td>    </tr>    <tr class="hidepage Node_Normal">        <td style="text-align:right">            <lang:node.base.limit/>        </td>        <td colspan="5">            <div class="form-inline">                <input type="text" class="form-control checkChange" style="width: 60px"                       value="0" name="limitTime">                <select class="form-control checkChange" name="limitType" style="width: 120px">                </select>                <span><lang:node.base.limit1/></span>                <input type="text" class="form-control checkChange" style="width: 60px"                       value="0" name="limitNum">                <span><lang:node.base.limit2/></span>                <input type="text" class="form-control checkChange" style="width: 60px"                       value="0" name="waringNum">                &nbsp;<span id="limitShow"></span><br>            </div>        </td>    </tr>    <tr style="font-size: 12px;" class="hidepage Node_Normal">        <td></td>        </td>        <td colspan="5">            <span style="color:red"><lang:node.base.limit3/></span>        </td>    </tr>    <tr id="trClassName">        <td style="text-align:right;width: 115px;">            <lang:node.base.msg1/>        </td>        <td colspan="5">            <input type="text" class="form-control checkChange" name="className"                   placeholder="<lang:node.base.msg2/>">        </td>    </tr>    <tr>        <td style="text-align:right;vertical-align: top">            <lang:node.base.memo/>        </td>        <td colspan="5">            <textarea class="form-control input-sm checkChange" style="resize:none" rows="3" name="memo"/>        </td>    </tr></table>');
	template.put('template/node/cluster.html', '<div class="chgPanel-group">    <div class="panel panel-white"><lang:node.cluster.a1/></div>    <div class="panel panel-white" ><lang:node.cluster.a2/>        <input type="text" name="clusterInteractive" class="form-control input-sm checkChange">    </div>    <div class="Node_Normal" >        <lang:node.cluster.a3/>        <br>        <span><lang:node.cluster.a4/></span>        <br>        <input type="text" name="clusterUrl" class="form-control input-sm checkChange">        <span style="color:red"><lang:node.cluster.a5/></span>        <br>        <br>        <span><lang:node.cluster.a6/></span>        <br>        <input type="text" name="clusterClassName" class="form-control input-sm checkChange">        <span style="color:red"><lang:node.cluster.a7/></span>        <br>        <br>        <span><lang:node.cluster.a8/><button type="button" class="btn-link btnExample" ><lang:example/></button></span>        <br>        <span><lang:node.cluster.a9/></span>    </div></div>');
	template.put('template/node/event.html', '<div class="chgPanel-group">    <table id="tblNodeEvent"></table>    <div class="panel panel-white" style="margin-top: 5px">        <button type="button" class="btn btn-danger btn-sm" id="btnEventDel"><lang:node.event.btnDel/></button>        <button type="button" class="btn btn-danger btn-sm" id="btnEventDelAll"><lang:node.event.btnDelAll/></button>        <button type="button" class="btn btn-info btn-sm pull-right" id="btnEventAdd"><lang:node.event.btnAdd/></button>    </div>    <div>        <input class="form-control input-sm hidden" name="eventId" value=""/>        <input class="form-control input-sm hidden" name="eventName" value=""/>        <input class="form-control input-sm hidden" name="eventClassName" value=""/>        <table border="0" style="width: 100%">            <tr>                <td style="width:60px;text-align:right"></td>                <td style="width:120px;text-align:left"></td>                <td style="width:40px;text-align:right"></td>                <td style="width:130px;text-align:left"></td>                <td style="width:30px;text-align:left"></td>            </tr>            <tr>                <td style="text-align:right"><lang:node.event.a3/></td>                <td>                    <select class="form-control input-sm"  name="customEventSelect"></select>                </td>                <td style="text-align:right"><lang:node.event.a2/></td>                <td>                    <select class="form-control input-sm" name="eventType"></select>                </td>            </tr>            <tr>                <td></td>                <td></td>                <td></td>                <td colspan="2">                    <button style="margin-right: 10px" class="btn btn-danger btn-sm pull-right" name="btnCustonEventDel"><lang:node.event.btnDel/></button>                    <button style="margin-right: 10px" class="btn btn-info btn-sm pull-right" name="btnCustonEventAdd"><lang:node.user.customBtnAdd/></button>                </td>            </tr>        </table>    </div></div>');
	template.put('template/node/exception.html', '<div class="chgPanel-group">    <table id="tblNodeException"></table>    <div class="panel panel-white" style="margin-top: 5px">        <button type="button" class="btn btn-danger btn-sm" id="btnExceptionDel"><lang:node.ex.btnDel/></button>        <button type="button" class="btn btn-danger btn-sm" id="btnExceptionDelAll"><lang:node.ex.btnDelAll/></button>        <button type="button" class="btn btn-info btn-sm pull-right" id="btnExceptionAdd"><lang:node.ex.btnAdd/></button>    </div>    <div >        <table border="0" style="width: 100%">            <tr>                <td style="width:120px;text-align:right"></td>                <td style="width:260px;text-align:left"></td>                <td style="width:20px;text-align:left"></td>                <td style="width:100px;text-align:right"></td>                <td style="width:200px;text-align:left"></td>            </tr>            <tr>                <td style="text-align:right"><lang:node.ex.a1/></td>                <td><select class="form-control input-sm" name="exceptionName"></select></td>                <td><input type="text" name="exName" class="form-control input-sm"  style="display:none"></td>                <td style="text-align:right"><lang:node.ex.a2/></td>                <td><input class="form-control input-sm" name="exceptionCode" disabled="true"></input></td>            </tr>            <tr>                <td style="text-align:right"><lang:node.ex.a3/></td>                <td colspan="2" id="tdExceptionMsg">                </td>                <td style="text-align:right"><lang:node.ex.a4/></td>                <td><select class="form-control input-sm" name="exceptionUser"></select></td>            </tr>            <tr>                <td style="text-align:right"><lang:node.ex.a5/></td>                <td><select class="form-control input-sm" name="exceptionDealType"></select></td>                <td colspan="3"><input type="text" name="exceptionDeal" class="form-control input-sm"  style="width:100%;display: none"></td>            </tr>            <tr><td></td><td></td>                <td colspan="3" style="display:none" class="exceptionDeal">                    <lang:node.ex.a6/><button type="button" class="btn-link btnExample" ><lang:example/></button>                </td>            </tr>        </table>    </div></div>');
	template.put('template/node/extendRule.html', '<div class="chgPanel-group">    <div class="panel panel-white">        <table>            <tr>                <td style="width:230px;text-align: right"><lang:node.rule.a1/>&nbsp;&nbsp;</td>                <td style="width:670px" >                    <input type="text" name="entryClassName" class="hzRadioInput" style="width: 100%"/>                </td>            </tr>            <tr>                <td></td><td><lang:node.rule.a2/><button type="button" class="btn-link btnExample" ><lang:example/></button></td>            </tr>            <tr>                <td >                    <button type="button" style="width: 200px" class="btn btn-info btn-sm" id="btnEditEntryRule"><lang:node.rule.a3/></button></td>                <td>                    <textarea name="entryRuleText" class="input-sm checkChange" readonly style="width:100%;resize:none" rows="4"></textarea>                    <textarea name="entryRuleScript" style="display: none"></textarea>                    <input type="hidden" name="entryRuleId"/>                </td>            </tr>        </table>    </div>    <div class="panel panel-white Node_Normal" style="display:none">        <table>            <tr>                <td style="width:230px;text-align: right"><lang:node.rule.a4/>&nbsp;&nbsp;</td>                <td style="width:670px" >                    <input type="text" name="leaveClassName" class="hzRadioInput" style="width: 100%"/>                </td>            </tr>            <tr>                <td></td><td><lang:node.rule.a2/><button type="button" class="btn-link btnExample" ><lang:example/></button></td>            </tr>            <tr>                <td >                    <button type="button" style="width: 200px" class="btn btn-info btn-sm" id="btnEditLeaveRule"><lang:node.rule.a5/></button></td>                <td>                    <textarea name="leaveRuleText" class="input-sm checkChange" readonly style="width:100%;resize:none" rows="3"></textarea>                    <textarea name="leaveRuleScript" style="display: none"></textarea>                    <input type="hidden" name="leaveRuleId"/>                </td>            </tr>        </table>    </div>    <div class="Node_Normal"  style="display:none">        <table>            <tr>                <td style="width:230px;text-align: right"><lang:node.rule.a6/>&nbsp;&nbsp;</td>                <td style="width:670px" >                    <select name="startModeType" style="width: 200px" class="checkChange hzRadioInput" >                        <option value="0"><lang:node.rule.a7/></option>                        <option value="1"><lang:node.rule.a8/></option>                        <option value="2"><lang:node.rule.a9/></option>                        <option value="3"><lang:node.rule.a10/></option>                    </select>                </td>            </tr>            <tr>                <td></td>                <td>                    <div >                        <div class="startModeType1">                            <div class="form-inline" >                                <span><lang:node.rule.a11/>&nbsp;&nbsp;</span>                                <select name="timeDate" class="checkChange hzRadioInput" style="width:150px;"></select><span>&nbsp;&nbsp;<lang:node.rule.a12/></span>                                <br>                                <label class="checkbox-inline" >                                    <input type="checkbox" class="checkChange" name="timeRetry" value="1"/>                                    <lang:node.rule.a13/>                                </label>                                <br>                                <span><lang:node.rule.a14/>&nbsp;&nbsp;</span>                                <input type="text" name="timeCycle" class="checkChange hzRadioInput" disabled="true" value="1000" style="width:100px"><span><lang:node.rule.a15/></span>                                <span><lang:node.rule.a16/>&nbsp;&nbsp;</span>                                <input type="text" name="num" class="checkChange hzRadioInput" disabled="true" value="0"  style="width:100px"><span><lang:node.rule.a17/></span>                                <br>                                <span><lang:node.rule.a18/><button type="button" class="btn-link btnExample" ><lang:example/></button></span>                                <br>                                <input type="text" name="timeClassName" style="width:530px" class="checkChange hzRadioInput" />                            </div>                        </div>                        <div class="startModeType2">                            <table>                                <tr>                                    <td style="width:55px"><lang:node.rule.a19/></td>                                    <td colspan="4" style="width:500px">                                        <select name="msgType" style="width: 200px" class="hzRadioInput">                                            <option value="2">JMS</option>                                        </select>                                    </td>                                </tr>                                <tr>                                    <td style="text-align: right"><lang:node.rule.a20/></td>                                    <td><input type="text" name="msgId" style="width: 200px" class="checkChange hzRadioInput" ></td>                                    <td style="text-align: right;width:50px"><lang:node.rule.a21/></td>                                    <td><input type="text" name="msgName" style="width: 200px" class="checkChange hzRadioInput" ></td>                                    <td></td>                                </tr>                                <tr>                                    <td style="text-align: right"><lang:node.rule.a22/></td>                                    <td><input type="text" name="msgFrom" style="width: 200px" class="checkChange hzRadioInput" ></td>                                    <td style="text-align: right"><lang:node.rule.a23/></td>                                    <td ><input type="text" name="msgTo" style="width: 200px" class="checkChange hzRadioInput" ></td>                                    <td></td>                                </tr>                                <tr>                                    <td style="text-align: right"><lang:node.rule.a24/></td>                                    <td><select name="msgPara" style="width: 200px" class="checkChange hzRadioInput" ></select></td>                                    <td style="text-align: right"><lang:node.rule.a25/></td>                                    <td><input type="text" name="msgClass" style="width: 350px" class="checkChange hzRadioInput" ></td>                                </tr>                                <tr>                                    <td></td><td></td>                                    <td colspan="2" style="text-align: right"><span><lang:node.rule.a26/><button type="button" class="btn-link btnExample" ><lang:example/></button></span></td>                                </tr>                            </table>                        </div>                        <div role="tabpanel" class="tab-pane  startModeType3">                            <div class="form-inline" >                                <span><lang:node.rule.a27/></span>                                <select name="signalPara" style="width: 300px" class="checkChange hzRadioInput" ></select>                                <br>                                <span><lang:node.rule.a18/><button type="button" class="btn-link btnExample" ><lang:example/></button></span>                                <br>                                <input type="text" name="signalClass" style="width:530px" class="checkChange hzRadioInput" />                            </div>                        </div>                    </div>                </td>            </tr>        </table>    </div></div>');
	template.put('template/node/nodePara.html', '<div class="chgPanel-group">    <table id="tblNodePara"></table>    <div class="panel panel-white">        <button type="button" class="btn btn-danger btn-sm" id="btnParaDel"><lang:node.para.btnDel/></button>        <button type="button" class="btn btn-danger btn-sm" id="btnParaDelAll"><lang:node.para.btnDelAll/></button>        <button type="button" class="btn btn-info btn-sm pull-right" id="btnParaAdd"><lang:node.para.btnAdd/></button>    </div>    <div >        <table border="0" style="width: 100%">            <tr>                <td style="width:90px;text-align:right"><lang:node.para.a1/></td>                <td style="width:140px;text-align:left">                    <input class="form-control input-sm" name="paraId" value=""/>                </td>                <td style="width:90px;text-align:right"><lang:node.para.a2/></td>                <td style="width:140px;text-align:left">                    <input class="form-control input-sm" name="paraName" value=""/>                </td>                <td style="width:90px;text-align:right"><lang:node.para.a3/></td>                <td style="width:140px;text-align:left">                    <input class="form-control input-sm" name="paraValue" value=""/>                </td>            </tr>        </table>    </div></div>');
	template.put('template/node/operator.html', '<div>    <ul class="nav nav-tabs tblNavBG" role="tablist" id="nav_operator">    </ul>    <div class="tab-content">        <div role="tabpanel" class="tab-pane active hzSecondTab tabSecondNode"  id="oAuthor"></div>        <div role="tabpanel" class="tab-pane hzSecondTab tabSecondNode" id="oSecondAuthor"></div>        <div role="tabpanel" class="tab-pane hzSecondTab tabSecondNode" id="oReader"></div>        <div role="tabpanel" class="tab-pane hzSecondTab tabSecondNode" id="oDone"></div>        <div role="tabpanel" class="tab-pane hzSecondTab tabSecondNode" id="oManager"></div>        <div role="tabpanel" class="tab-pane hzSecondTab tabSecondNode" id="oCreator"></div>    </div></div>');
	template.put('template/node/participant.html', '<div>    <ul class="nav nav-tabs tblNavBG" role="tablist" id="nav_participant"></ul>    <div class="tab-content" >        <div role="tabpanel" class="tab-pane active hzSecondTab tabSecondNode"  id="pAuthor"></div>        <div role="tabpanel" class="tab-pane hzSecondTab tabSecondNode" id="pSecondAuthor"></div>        <div role="tabpanel" class="tab-pane hzSecondTab tabSecondNode" id="pReader"></div>    </div></div>');
	template.put('template/node/subflow.html', '<div class="chgPanel-group">    <div style="width:950px">        <table id="tblNodeSubflow"></table>    </div>    <div class="panel panel-white" style="width:950px;margin-top: 5px;">        <button type="button" class="btn btn-danger btn-sm" id="btnSubflowDel"><lang:node.sub.btnDel/></button>        <button type="button" class="btn btn-danger btn-sm" id="btnSubflowDelAll"><lang:node.sub.btnDelAll/></button>        <button type="button" class="btn btn-info btn-sm" id="btnSubflowAdd"><lang:node.sub.btnAdd/></button>        <label class="checkbox-inline pull-right">            <input type="checkbox" name="wait" value="1" class="checkChange" checked/><lang:node.sub.a1/>        </label>        <label class="checkbox-inline pull-right">&nbsp;</label>        <label class="checkbox-inline pull-right">            <input type="checkbox" name="multi" value="1" class="checkChange"/><lang:node.sub.a2/>        </label>    </div>    <div id="divSubAuthor" style="display: none">        <lang:node.sub.a9/>        <div class="">            <button type="button" class="btn btn-danger btn-sm pull-right" id="btnOrgDelAll"><lang:node.user.btnDelAll/></button>            <button type="button" class="btn btn-danger btn-sm pull-right" id="btnOrgDel"><lang:node.user.btnDel/></button>            <button type="button" class="btn btn-info btn-sm pull-right" id="btnOrgAdd"><lang:node.user.btnAdd/></button>        </div>        <table id="tblUserOrg"></table>    </div>    <div style="height: 20px;"><lang:node.sub.a3/></div>    <div  style="width: 950px">        <lang:node.sub.a4/><select style="width:90px" name="mainVar" class="hzRadioInput"></select>        <label class="radio-inline">            <input type="radio" name="varType" value="IN" checked/><lang:node.sub.a5/>        </label>        <label class="radio-inline ">            <input type="radio" name="varType" value="OUT"/><lang:node.sub.a6/>        </label>        <label class="radio-inline ">            <input type="radio" name="varType" value="INOUT"/><lang:node.sub.a7/>        </label>        <lang:node.sub.a8/><select style="width:90px" name="subVar" class="hzRadioInput"></select>        <button type="button" class="btn btn-danger btn-sm pull-right" id="btnSubParaDelAll"><lang:node.sub.btnDelAll/></button>        <button type="button" class="btn btn-danger btn-sm pull-right" id="btnSubParaDel"><lang:node.sub.btnDel/></button>        <button type="button" class="btn btn-info btn-sm pull-right" id="btnSubParaAdd" disabled><lang:node.sub.btnAdd/></button>    </div>    <div style="width:950px;margin-top:10px">        <table id="tblNodeSubPara"></table>    </div></div>');
	template.put('template/node/user/userCustomer.html', '<label class="checkbox-inline">    <input type="checkbox" name="customerCheck" value="1"  class="checkChange" />    <lang:node.user.c1/></label><textarea name="customerMemo" class="input-sm checkChange"          style="width:100%;resize:none;margin-top: 5px" rows="9"></textarea><p><lang:node.user.c2/><button type="button" class="btn-link btnExample" ><lang:example/></button></p><div style="width: 100%">    <index type="text" style="overflow: hidden" class="checkchange customerClass" name="customerClass"/>    <select name="customClassSelect" style="width: 76%;height: 35px;">    </select>    <button style="margin-right: 5px" class="btn btn-danger btn-sm pull-right" name="delUserCustomClassBtn"><lang:node.user.btnDel/></button>    <button style="margin-right: 5px" class="btn btn-info btn-sm pull-right" name="addUserCustomClassBtn"><lang:node.user.customBtnAdd/></button></div>');
	template.put('template/node/user/userField.html', '<div style="width: 600px">    <div><lang:node.user.f1/></div>    <div class="form-inline">        <table >            <tr>                <td ><lang:node.user.f2/></td>                <td><lang:node.user.f3/></td>                <td ></td>            </tr>            <tr>                <td><select name="userForm" style="width:190px"></select></td>                <td><select name="userField" style="width:190px"></select>                    <input type="text" name="userField" style="width:190px;display: none"></td>                <td >                    <div class="btn-group" style="width: 220px">                        <button type="button" class="btn btn-info btn-sm" id="btnFieldAdd"><lang:node.user.btnAdd/></button>                        <button type="button" class="btn btn-danger btn-sm  pull-right" id="btnFieldDel"><lang:node.user.btnDel/></button>                        <button type="button" class="btn btn-danger btn-sm  pull-right" id="btnFieldDelAll"><lang:node.user.btnDelAll/></button>                    </div>                </td>            </tr>        </table>    </div>    <table id="tblUserField"></table></div>');
	template.put('template/node/user/userOrg.html', '<div style="width: 620px">    <table id="tblUserOrg"></table>    <div class="btn-group pull-right">        <button type="button" class="btn btn-info btn-sm" id="btnOrgAdd"><lang:node.user.btnAdd/></button>        <button type="button" class="btn btn-danger btn-sm" id="btnOrgDel"><lang:node.user.btnDel/></button>        <button type="button" class="btn btn-danger btn-sm" id="btnOrgDelAll"><lang:node.user.btnDelAll/></button>    </div></div>');
	template.put('template/node/user/userRelation.html', '<div class="panel panel-white" >    <table border="0" style="width: 100%">        <tr>            <td style="width:80px;text-align:right"></td>            <td style="width:220px;text-align:left"></td>            <td style="width:80px;text-align:left"></td>            <td style="width:220px;text-align:right"></td>        </tr>        <tr>            <td style="width: 150px;"><lang:node.user.r1/></td>            <td><select class="form-control input-sm" name="rNode"></select></td>            <td><input type="text" name="rNode" style="width:100%;display:none" readonly></td>        </tr>        <tr>            <td><lang:node.user.r2/></td>            <td colspan="2">                <select class="form-control input-sm" name="rBase"></select>            </td>        </tr>        <tr>            <td><lang:node.user.r3/></td>            <td colspan="2" width="300px"><select class="form-control input-sm" name="relation"></select></td>        </tr>    </table></div><div class="panel panel-white" style="margin-top: 5px">    <button type="button" class="btn btn-danger btn-sm" id="btnRelationDel"><lang:node.user.btnDel/></button>    <button type="button" class="btn btn-danger btn-sm" id="btnRelationDelAll"><lang:node.user.btnDelAll/></button>    <button type="button" class="btn btn-info btn-sm pull-right" id="btnRelationAdd"><lang:node.user.btnAdd/></button></div><table id="tblUserRelation"></table>');
	template.put('template/node/user/userRule.html', '<button type="button" class="btn btn-info btn-sm" id="btnEditUserRule"><lang:node.user.r4/></button><textarea name="userRuleText" class="input-sm checkChange" readonly          style="width:100%;resize:none;margin-top: 5px" rows="12"></textarea><textarea name="userRuleScript" style="display: none"></textarea><input type="hidden" name="userRuleId"/>');
	template.put('template/node/user/userVar.html', '<div style="width: 625px">    <div><lang:node.user.r5/></div>    <table id="tblUserVar"></table></div>');
	template.put('template/node/user.html', '<div>    <ul class="nav nav-tabs tblNavBG" role="tablist" id="navUser">        <li role="presentation" class="active">            <a href="#userOrg" aria-controls="userOrg" role="tab" data-toggle="tab"><lang:node.user.t1/></a>        </li>        <li role="presentation">            <a href="#userField" aria-controls="userField" role="tab" data-toggle="tab"><lang:node.user.t2/></a>        </li>        <li role="presentation">            <a href="#userVar" aria-controls="userVar" role="tab" data-toggle="tab"><lang:node.user.t3/></a>        </li>        <li role="presentation">            <a href="#userRelation" aria-controls="userRelation" role="tab" data-toggle="tab"><lang:node.user.t4/></a>        </li>        <li role="presentation">            <a href="#userRule" aria-controls="userRule" role="tab" data-toggle="tab"><lang:node.user.t5/></a>        </li>        <li role="presentation">            <a href="#userCustomer" aria-controls="userCustomer" role="tab" data-toggle="tab"><lang:node.user.t6/></a>        </li>    </ul>    <div class="tab-content">        <div role="tabpanel" class="tab-pane active hzSecondTab tabUser"  id="userOrg"></div>        <div role="tabpanel" class="tab-pane hzSecondTab tabUser" id="userField"></div>        <div role="tabpanel" class="tab-pane hzSecondTab tabUser" id="userVar"></div>        <div role="tabpanel" class="tab-pane hzSecondTab tabUser" id="userRelation"></div>        <div role="tabpanel" class="tab-pane hzSecondTab tabUser" id="userRule"></div>        <div role="tabpanel" class="tab-pane hzSecondTab tabUser" id="userCustomer"></div>    </div>    <div class="tabUserPro">        <div class="form-inline" id="sendMsg" style="margin-left: 10px;margin-top: 5px;"></div>        <div class="form-inline" id="control" style="margin-left: 10px;margin-right: 5px;margin-top: 15px"></div>    </div></div>');
	template.put('template/node.html', '<div>    <div>        <ul class="nav nav-tabs tblNavBG" role="tablist" id="navTabs"> </ul>        <div class="tab-content">            <div role="tabpanel" class="tab-pane hzTab tabNode" id="base"></div>            <div role="tabpanel" class="tab-pane hzTab tabNode" id="participant"></div>            <div role="tabpanel" class="tab-pane hzTab tabNode" id="operator"></div>            <div role="tabpanel" class="tab-pane hzTab tabNode" id="event"></div>            <div role="tabpanel" class="tab-pane hzTab tabNode" id="subflow"></div>            <div role="tabpanel" class="tab-pane hzTab tabNode" id="extendRule"></div>            <div role="tabpanel" class="tab-pane hzTab tabNode" id="exception"></div>            <div role="tabpanel" class="tab-pane hzTab tabNode" id="nodePara"></div>            <div role="tabpanel" class="tab-pane hzTab tabNode" id="cluster"></div>        </div>        <div class="tabNodeSel" >           <select id="selectNode" style="width:99%"></select>        </div>    </div></div>');
	template.put('template/part.html', '<div class="fd-part-ck" data-part="file">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.file/></div></div><div class="fd-line">    <div class="fd-line-img"></div></div><div class="fd-part" data-part="Start">    <div class="fd-part-img" ></div>    <div class="fd-part-text"><lang:part.start/></div></div><div class="fd-part" data-part="Node">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.task/></div></div><div class="fd-part" data-part="Event">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.event/></div></div><div class="fd-part" data-part="Gateway">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.gateway/></div></div><div class="fd-part" data-part="Robot">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.auto/></div></div><div class="fd-part" data-part="Cluster">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.cluster/></div></div><div class="fd-part" data-part="Subflow">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.subflow/></div></div><div class="fd-part" data-part="Virtual">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.virtual/></div></div><div class="fd-part" data-part="End">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.end/></div></div><div class="fd-line">    <div class="fd-line-img"></div></div><div class="fd-part-ck" data-part="line">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.line/></div></div><div class="fd-part-ck" data-part="brokenline">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.broken/></div></div><div class="fd-part-ck" data-part="swimlanes">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.swimlane/></div></div><div class="fd-line">    <div class="fd-line-img"></div></div><div class="fd-part-ck selected" data-part="select">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.select/></div></div><div class="fd-part-ck" data-part="align">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.align/></div></div><div class="fd-part-ck" data-part="clear">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.clear/></div></div><div class="fd-part-ck" data-part="gridlines">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.gridlines/></div></div><div class="fd-line">    <div class="fd-line-img"></div></div><div class="fd-part-ck" data-part="zoomout">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.zoomout/></div></div><div class="fd-part-ck" data-part="zoomin">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.zoomin/></div></div><div class="fd-part-ck" data-part="zoomreset">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.zoomreset/></div></div>');
	template.put('template/part1.html', '<div class="fd-line">    <div class="fd-line-img"></div></div><div class="fd-part" data-part="Start">    <div class="fd-part-img" ></div>    <div class="fd-part-text"><lang:part.start/></div></div><div class="fd-part" data-part="Node">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.task/></div></div><div class="fd-part" data-part="Event">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.event/></div></div><div class="fd-part" data-part="Gateway">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.gateway/></div></div><div class="fd-part" data-part="Robot">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.auto/></div></div><div class="fd-part" data-part="Cluster">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.cluster/></div></div><div class="fd-part" data-part="Subflow">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.subflow/></div></div><div class="fd-part" data-part="Virtual">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.virtual/></div></div><div class="fd-part" data-part="End">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.end/></div></div>');
	template.put('template/part8.html', '<div class="fd-part-ck" data-part="file">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.file/></div></div><div class="fd-line">    <div class="fd-line-img"></div></div><div class="fd-part-ck" data-part="line">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.line/></div></div><div class="fd-part-ck" data-part="brokenline">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.broken/></div></div><div class="fd-part-ck" data-part="swimlanes">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.swimlane/></div></div><div class="fd-line">    <div class="fd-line-img"></div></div><div class="fd-part-ck selected" data-part="select">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.select/></div></div><div class="fd-part-ck" data-part="align">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.align/></div></div><div class="fd-part-ck" data-part="clear">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.clear/></div></div><div class="fd-part-ck" data-part="gridlines">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.gridlines/></div></div><div class="fd-line">    <div class="fd-line-img"></div></div><div class="fd-part-ck" data-part="zoomout">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.zoomout/></div></div><div class="fd-part-ck" data-part="zoomin">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.zoomin/></div></div><div class="fd-part-ck" data-part="zoomreset">    <div class="fd-part-img"></div>    <div class="fd-part-text"><lang:part.zoomreset/></div></div>');
	template.put('template/popwin.html', '<!--禁止动画效果.如果你不需要模态框弹出时的动画效果（淡入淡出效果），删掉 .fade 类即可。class="modal fade"--><!-- 删除 tabindex="-1" 属性 与confirm冲突--><div class="modal" id="hzPopModal" role="dialog" aria-labelledby="hzPopModalLabel"     data-backdrop="static">    <div class="modal-dialog" style="width:700px" role="document" aria-hidden="true">        <div class="modal-content">            <div class="modal-header" style="height: 45px;background-color: rgba(0,1,0,0.04)">                <button type="button" class="close" data-dismiss="modal" aria-label="Close">                    <span aria-hidden="true">&times;</span>                </button>                <h4 class="modal-title moduleTitle" id="hzPopModalLabel">Modal title</h4>            </div>            <div class="modal-body" style="padding-top:5px;height: 450px;background-color: rgba(0,1,0,0.04)">                <p>One fine body&hellip;</p>            </div>            <div class="modal-footer" style="background-color: rgba(0,1,0,0.04)">                <button type="button" class="btn btn-primary" id="okBtn"><lang:popwin.ok/></button>                <button type="button" class="btn btn-default" data-dismiss="modal"><lang:popwin.cancel/></button>                <button type="button" class="btn btn-info" id="applyBtn"><lang:popwin.apply/></button>            </div>        </div>    </div></div>');
	template.put('template/router/base.html', '<table>    <tr style="height: 40px">        <td style="width:180px" align="right"><lang:router.base.id/></td>        <td style="width:80%"><input type="text" name="routerId" style="width:100%" disabled></td>    </tr>    <tr  style="height: 40px">        <td align="right"><lang:router.base.name/></td>        <td><input type="text" name="routerName" class="checkChange" style="width:100%"></td>    </tr>    <tr  style="height: 40px">        <td align="right"><lang:router.base.no/></td>        <td><input type="text" name="routerSort" class="checkChange" style="width:100%"></td>    </tr>    <tr >        <td align="right" valign="top"><lang:router.base.memo/></td>        <td><textarea name="memo" class="form-control input-sm checkChange"               rows="10" maxlength="1000" style="resize:none" ></textarea></td>    </tr></table>');
	template.put('template/router/condition.html', '<div class="panel panel-white" style="margin-bottom:5px;color:red"><lang:router.condition.memo/></div><div class="panel panel-white form-inline" style="margin-bottom:5px;">    <table border="0">        <tr>            <td width="80px"></td>            <td width="60px"></td>            <td width="250px"></td>            <td width="110px"></td>            <td width="250px"></td>            <td width="60px"></td>            <td></td>        </tr>        <tr>            <td>                <select name="conType" class="hzRadioInput"  style="width: 100%">                    <option value="&&"><lang:router.condition.t1/></option>                    <option value="||"><lang:router.condition.t2/></option>                </select>            </td>            <td>                <input type="text" name="leftBrackets" class="hzRadioInput" style="width: 100%" value="(">            </td>            <td>                <select name="conVar" class="hzRadioInput"  style="width: 100%"></select>            </td>            <td>                <select name="conOperator" class="hzRadioInput"  style="width: 100%"></select>            </td>            <td>                <input type="text" name="conTxt" class="hzRadioInput"  style="width: 100%;">            </td>            <td>                <input type="text" name="rightBrackets" class="hzRadioInput" style="width: 100%" value=")">            </td>            <td>            </td>        </tr>    </table></div><div class="panel panel-white" style="margin-bottom:5px">    <div style="width:815px">        <textarea name="condition" style="width:100%;resize:none;" rows="8"></textarea><!--        <table id="tblCondition" ></table>-->    </div>    <div class="tabConditionBtn">        <button type="button" style="width: 80px; margin-bottom: 5px;" class="btn btn-info btn-sm" id="btnAddCondition"><lang:router.condition.btnAdd/></button><!--        <button type="button" class="btn btn-info btn-sm" id="btnEditCondition"><lang:router.condition.btnEdit/></button>--><!--        <button type="button" class="btn btn-info btn-sm" id="btnInsertCondition"><lang:router.condition.btnInsert/></button>--><!--        <button type="button" class="btn btn-info btn-sm" id="btnDelCondition"><lang:router.condition.btnDel/></button>-->        <button type="button" style="width: 80px;" class="btn btn-info btn-sm" id="btnDelAllCondition"><lang:router.condition.btnDel/></button><!--        <button type="button" class="btn btn-info btn-sm" id="btnChgCondition"><lang:router.condition.btnChg/></button>-->    </div></div><div>    <table>        <tr>            <td style="width:130px;text-align: right"><lang:router.condition.msg1/></td>            <td style="width:85%" >                <input type="text" name="routerClassName" class="hzRadioInput" style="width: 100%"/>            </td>        </tr>        <tr><td></td><td><p><lang:router.condition.msg2/><button type="button" class="btn-link btnExample" ><lang:example/></button></p></td></tr>        <tr>            <td valign="top" align="right">                <button type="button" class="btn btn-info btn-sm" id="btnEditRouterRule"><lang:router.condition.btnRule/></button>            </td>            <td>                <textarea name="routerRuleText" class="input-sm checkChange" readonly style="width:100%;resize:none" rows="6"></textarea>                <textarea name="routerRuleScript" style="display: none"></textarea>                <input type="hidden" name="routerRuleId"/>            </td>        </tr>    </table></div>');
	template.put('template/router/scope.html', '<div class="panel panel-white" style="margin-bottom: 10px"><table>    <tr>        <td style="width: 182px"><lang:router.scope.msg1/></td>        <td style="width: 50px"></td>        <td style="width: 182px"><lang:router.scope.msg2/></td>        <td style="width: 50px"></td>        <td style="width: 182px"><lang:router.scope.msg3/></td>    </tr>    <tr>        <td><select multiple name="includes" style="width:100%;height: 230px;">        </select></td>        <td align="center">            <button type="button" class="btn btn-info btn-sm" id="btnLeftAdd"><<</button><br><br>            <button type="button" class="btn btn-info btn-sm" id="btnLeftDel">>></button>        </td>        <td><select multiple name="allNodes" style="width:100%;height:  230px">        </select></td>        <td align="center">            <button type="button" class="btn btn-info btn-sm" id="btnRightAdd">>></button><br><br>            <button type="button" class="btn btn-info btn-sm" id="btnRightDel"><<</button>        </td>        <td><select multiple name="executions" style="width:100%;height:  230px">        </select></td>    </tr></table></div><div style="color:red"><lang:router.scope.msg4/></div>');
	template.put('template/router.html', '<div>    <div>        <ul class="nav nav-tabs" role="tablist" id="navTabs">            <li role="presentation" class="active">                <a href="#base" aria-controls="base" role="tab" data-toggle="tab"><lang:router.base.title/></a>            </li>        </ul>        <div class="tab-content">            <div role="tabpanel" class="tab-pane active hzTab tabRouter" id="base"></div>            <div role="tabpanel" class="tab-pane hzTab tabRouter" id="condition"></div>            <div role="tabpanel" class="tab-pane hzTab tabRouter" id="scope"></div>        </div>    </div></div>');
	template.put('template/status.html', '<div class="fd-bars">    <div class="fd-bar" data-part="user">        <div class="fd-bar-title"><lang:status.user/></div>        <div class="fd-bar-text">　</div>    </div>    <div class="fd-bar" data-part="pos">        <div class="fd-bar-title"><lang:status.pos/></div>        <div class="fd-bar-text">　</div>    </div>    <div class="fd-bar" data-part="flowname">        <div class="fd-bar-title"><lang:status.flowname/></div>        <div class="fd-bar-text">　</div>    </div>    <div class="fd-bar" data-part="flowid">        <div class="fd-bar-title"><lang:status.flowid/></div>        <div class="fd-bar-text">　</div>    </div>    <div class="fd-bar" data-part="type">        <div class="fd-bar-title"><lang:status.type/></div>        <div class="fd-bar-text" >　</div>    </div>    <div class="fd-bar" data-part="ver">        <div class="fd-bar-title"></div>    </div></div>');
	

	return template;

});
/**
 * 流程节点连接线(直线或者折线)
 * @author liys 201903
 */
define('flowdesigner/element/FlowLine',['require','jquery','zrender','../Template'],function(require) {

    var $ = require('jquery'),
        zRender = require('zrender'),
        Template = require('../Template');
    var FlowLine = function(opts) {
        for (var name in opts) {
            this[name] = opts[name];
        }

        this._setShape();
    };

    FlowLine.prototype = {
        constructor: FlowLine,
        __Flowdesigner:null,  //画布框架对象
        __drawLayer:null,     //画布数据对象

        id: 'Line', //路由id
        name:'路由',    //路由名称
        data:{},  //路由设置对象json(用于点击路由时,显示路由属性设置)
        map:{},   //图形数据对象

        lineType:1,     //线条类型1=直线,2=折线
        fromNode:null,  //路由开始节点对象FlowNode
        toNode:null,    //路由结束节点对象FlowNode
        tmpNode:null,   //用于修改开始结束节点时,临时记录原来的节点对象,用于恢复

        x1:null,y1:null,x2:null,y2:null,    //开始结束节点的顶点坐标,用于计算路由点坐标

        points:[],      //路由连接线的点坐标,在节点变化时需要重新计算
        arrowPoints:[], //箭头坐标点
        txtPoint:[],//字体的位置点
        dragPoints:[],  //可以拖动的点
        dragTmpPoint:null, //如果被拖动过,则记录最后的拖动点坐标,用于恢复
        deletePoint:[], //删除图片坐标点
        txtOnRoute:true, //文字位置是否在线的上方

        zrGroup:null,    //路由图形组
        lineShape: null, //连接线对象
        arrowShape: null,//箭头对象
        txtShape:null,      //路由文字对象
        dragShapes: [],//可以拖动的点对象
        deleteShape:null,//删除图标

        //不可修改值,自动计算
        _setId:function(){
            if(this.id == 'Line') {
                this.id += this.__drawLayer.routeMax;
                this.name += this.__drawLayer.routeMax;
                this._setName();
                this.__drawLayer.routeMax += 1;
            }
        },
        //路由名称修改
        _setName:function(){
            this.txtShape.attr("style",{
                x:this.txtPoint[0],
                y:this.txtPoint[1],
                truncate: {
                    outerWidth: 150
                },
                text:this.name
            });

            this.txtShape.position = [0,this.txtOnRoute?-8:10];
        },
        //获取箭头的坐标点
        _getArrowPoints: function(pointArray) {
            var arrowHeight=20,arrowAngle=13;
            var fromPoint = pointArray[pointArray.length - 2],
                toPoint   = pointArray[pointArray.length - 1],
                angle = Math.atan2(fromPoint[0] - toPoint[0], fromPoint[1] - toPoint[1]) / Math.PI * 180;

            toPoint = [this.dragPoints[1].x,this.dragPoints[1].y];

            var xPoint = [
                    toPoint[0] + Math.sin(2 * Math.PI / 360 * (angle - arrowAngle)) * arrowHeight,
                    toPoint[1] + Math.cos(2 * Math.PI / 360 * (angle - arrowAngle)) * arrowHeight
                ],
                yPoint = [
                    toPoint[0] + Math.sin(2 * Math.PI / 360 * (angle + arrowAngle)) * arrowHeight,
                    toPoint[1] + Math.cos(2 * Math.PI / 360 * (angle + arrowAngle)) * arrowHeight
                ];

            //删除图片的坐标点
            if(xPoint[0] > toPoint[0]){
                this.deletePoint = xPoint;
            }
            else{
                this.deletePoint = yPoint;
            }

            return [toPoint, xPoint, yPoint];
        },
        _showTypeisDesigner:function(){
            var showtype = this.__Flowdesigner.showtype;
            return showtype ==1 || showtype ==5;
        },
        //创建箭头对象,执行一次,后面通过setShape来改变位置
        _makeArrowShape: function(pointArray) {
            var self = this;
            this.arrowPoints = this._getArrowPoints(pointArray);
            this.arrowShape = new zRender.Polygon({
                __route: self,
                z:self.__drawLayer.getZLevel(self.__Flowdesigner.zArr.route),
                style: {
                    strokeNoScale: true, //描边粗细不随缩放而改变，false 则会根据缩放同比例缩放描边粗细。
                    transformText: true, //文字是否跟随变换效果，仅对 Path 或 Image 元素有效
                    fill: '#979797'
                },
                shape: {
                    points: this.arrowPoints
                }
            });
            this._bindEvent(this.arrowShape);
        },
        //创建多边形折线段对象,执行一次,后面通过setShape来改变点的位置
        _makeLineShape: function(pointArray) {
            var self = this;
            this.lineShape = new zRender.Polyline({
                __route: self,
                z:self.__drawLayer.getZLevel(self.__Flowdesigner.zArr.route),
                style: {
                    strokeNoScale: true, //描边粗细不随缩放而改变，false 则会根据缩放同比例缩放描边粗细。
                    transformText: true, //文字是否跟随变换效果，仅对 Path 或 Image 元素有效
                    stroke: '#979797',
                    lineWidth: 2,
                    lineJoin: 'round'
                },
                shape: {
                    points: pointArray
                }
            });
            this._bindEvent(this.lineShape);
        },
        //创建路由文字显示
        _makeTxtShape:function(){
            var self = this;
            this.txtShape = new zRender.Text({
                __route: self,
                z:self.__drawLayer.getZLevel(self.__Flowdesigner.zArr.route),
                position:[0,self.txtOnRoute?-8:10],
                style:{
                    strokeNoScale: true, //描边粗细不随缩放而改变，false 则会根据缩放同比例缩放描边粗细。
                    transformText: true, //文字是否跟随变换效果，仅对 Path 或 Image 元素有效
                    x:self.txtPoint[0],
                    y:self.txtPoint[1],
                    textPosition:'inside',
                    textAlign:'center',
                    textVerticalAlign:'middle',
                    text:this.name
                }
            });
            this._bindEvent(this.txtShape);
        },
        //绑定事件
        _bindEvent: function (objCanvas) {
            var self= this;
            if (self._showTypeisDesigner()) {
                objCanvas
                    .on('mouseover', function (param) {
                        if(self.__Flowdesigner.selLineHandler != self) {
                            self._chgForMousemove(false);
                        }
                        self.__Flowdesigner.showTitle(self.name + "[" + self.id + "]",
                            {x: param.event.zrX, y: param.event.zrY});
                    })
                    .on('mouseout', function () {
                        if(self.__Flowdesigner.selLineHandler != self){
                            self._chgForMousemove(true);
                        }
                        self.__Flowdesigner.hideTitle();
                    })
                    .on('click', function () {
                        self._clickLine();
                    })
                    .on('contextmenu', function (param) {
                        self._showContextMenu(param);
                    });
            }
            else{
                objCanvas
                    .on('mouseover', function (param) {
                        self.__Flowdesigner.showTitle(self.name + "[" + self.id + "]",
                            {x: param.event.zrX, y: param.event.zrY});
                    })
                    .on('mouseout', function () {
                        self.__Flowdesigner.hideTitle();
                    });
            }
        },

        //创建可以拖动的点对象
        _makeDragShapes: function() {
            var self = this;
            this.dragShapes = [];
            $.each(this.dragPoints  || [], function(i, point) {
                self._makeCircleShape(point);
            });
        },
        //创建点对象
        _makeCircleShape: function (point) {
            var x = point.x, y = point.y, index = point.pos;
            var self = this;
            var circle = new zRender.Circle({
                __route: self,
                z: self.__drawLayer.getZLevel(self.__Flowdesigner.zArr.selected),
                style: {
                    stroke: '#FF8600',
                    fill: 'yellow',
                    opacity: '1'
                },
                position: [0, 0],
                shape: {
                    cx: x,
                    cy: y,
                    r: 4
                },
                draggable: index == 2, //只有中间点允许拖动
                ondragend: function () {
                }

            });
            if (index == 2) {
                //三段折线的拖动点事件
                circle.on('drag', function (param) {
                    self._dragLinePoint(this, param.event.zrX, param.event.zrY);
                });
            }
            else if (index == 3) {
                //两段折线的方向改变事件
                circle.on('click', function (param) {
                    self._chgLineDirector(this, param.event.zrX, param.event.zrY);
                });
            }
            else {
                //路由指向和起始节点变化
                circle.on('click', function (param) {
                    self._chgLineNode(this, param.event.zrX, param.event.zrY);
                });
            }
            circle.hide();
            self.dragShapes.push(circle);
        },
        //创建删除图标
        _makeDeleteShape:function(){
            var self = this;
            var opts = this.__Flowdesigner.options;
            this.deleteShape = new zRender.Image({
                __route: self,
                z:self.__drawLayer.getZLevel(self.__Flowdesigner.zArr.selected),
                position: [0,0],
                style: {
                    x:self.deletePoint[0],
                    y:self.deletePoint[1],
                    image:opts.imgBasePath + opts.flownode.image['deleteurl'],
                    width:  13,
                    height: 11
                },
                onclick: function(param) {
                    // console.log(self.name + '要删除了哦');
                    self._deleteClick();
                }
            });

            this.deleteShape.hide();
        },
        //点击路由处理
        _clickLine:function(){
            // console.log(this.name +"路由被点击");
            var  fd = this.__Flowdesigner;
            if(this.__drawLayer.isScale()){
                return;
            }
            if(fd.startSelArea){
                //拖动结束点移动到路由上时,不触发节点的click事件
                return;
            }
            if(!fd.dragLineHandler){
                fd.cancelSel();
                //显示当前路由的拖动点
                this._invisibleDragPoint(false);
                fd.selLineHandler = this;
            }
        },
        //取消路由选中状态
        cancelSel:function(){
            this._invisibleDragPoint(true);
            this.__Flowdesigner.selLineHandler = null;
        },
        //鼠标移动到对象上时的处理
        _chgForMousemove:function(hidden){
            var corlor = hidden?'#979797':'#2b9727';
            var z = this.__drawLayer.getZLevel(this.__Flowdesigner.zArr.route + (hidden?0:1));
            this.lineShape.attr({
                z:z,
                style: {
                    stroke: corlor
                }
            });
            this.arrowShape.attr({
                z:z,
                style:{
                    fill:corlor
                }
            });
            this.txtShape.attr({
                z:z,
                style:{
                    textFill:hidden?'#000':'#2b9727'
                }
            });
        },
        //是否隐藏拖动点,true,隐藏,false不隐藏(选中时显示)
        _invisibleDragPoint:function(hidden){
            var self = this;
            $.each(this.dragPoints || [],function(i,dragShape){
                hidden?self.dragShapes[i].hide():self.dragShapes[i].show();
            });
            //3段和4段切换时的处理
            if(this.dragPoints.length < this.dragShapes.length){
                this.dragShapes[this.dragShapes.length-1].hide();
            }

            self._chgForMousemove(hidden);

            //显示删除图标
            if(hidden){
                this.deleteShape.hide();
            }
            else{
                this.deleteShape.show();
            }
        },
        //重新计算路由的各个点坐标
        _initPoint:function(){
            var self = this;
            var imageWidth =50,imageHeight=50;
            var startPoint = {
                x:this.x1,
                y:this.y1
            }
            var endPoint ={
                x: this.x2,
                y: this.y2
            };

            if(this.fromNode){
                this.x1 = this.fromNode.x;
                this.y1 = this.fromNode.y;

                if(imageWidth < this.fromNode.imageWidth){
                    imageWidth = this.fromNode.imageWidth;
                    imageHeight = this.fromNode.imageHeight;
                }

                startPoint ={
                    x: this.x1 + this.fromNode.imageWidth/2,
                    y: this.y1 + this.fromNode.imageHeight/2
                };
            }
            else{
                //可能在拖动中
                this.__drawLayer.checkPoint(this.x1,this.y1);
            }

            if(this.toNode){
                this.x2 = this.toNode.x;
                this.y2 = this.toNode.y;
                if(imageWidth < this.toNode.imageWidth){
                    imageWidth = this.toNode.imageWidth;
                    imageHeight = this.toNode.imageHeight;
                }

                endPoint ={
                    x: this.x2 + this.toNode.imageWidth/2,
                    y: this.y2 + this.toNode.imageHeight/2
                };
            }
            else{
                //可能在拖动中
                this.__drawLayer.checkPoint(this.x2,this.y2);
            }
            //开始点
            this.points = [startPoint];

            if(this.lineType == 2){
                //折线时,计算中间的一个或者两个点
                this._makeBrokenLinePoints({
                    x1: startPoint.x - imageWidth / 2,
                    y1: startPoint.y - imageHeight / 2,
                    x2: endPoint.x - imageWidth / 2,
                    y2: endPoint.y - imageHeight / 2,
                    rectWidth: imageWidth,
                    rectHeight: imageHeight,
                    rectWidthCenter: imageWidth / 2,
                    rectHeightCenter: imageHeight / 2,

                    minWidth:25,
                    minHeight:25
                });
                //上面的方法执行完毕后,this.points中会存放已经算好的点,
                //恢复数据初始化时
                if(this.dragTmpPoint ){
                    if(this.points.length == 3){
                        //说明线段是3段折线
                        if(this.points[1].x == this.points[2].x){
                            //说明中间的线段是竖向,拖动时x值会变化(也就是左右拖动)
                            this.points[1].x = this.dragTmpPoint.x;
                            this.points[2].x = this.dragTmpPoint.x;
                        }
                        else{
                            //说明中间的线段是横向,拖动时y值会变化(也就是上下拖动)
                            this.points[1].y = this.dragTmpPoint.y;
                            this.points[2].y = this.dragTmpPoint.y;
                        }
                    }
                    else if(this.points.length == 2){
                        //说明线段是2段线段,为了能够手动调整折线方向,
                        // 如果中间点不是默认点,则说明被修改过
                        //初始化时不做判断,直接修改
                        this.points[1].x = this.dragTmpPoint.x;
                        this.points[1].y = this.dragTmpPoint.y;
                    }
                    else{
                        //出现错误了
                        $.confirm({
                            title: fd.getLang('static.warning'),
                            content: fd.getLang('static.routeInit').replace('name',self.name),
                            type: 'red',
                            icon: 'glyphicon glyphicon-info-sign',
                            buttons: {
                                ok: {
                                    text: fd.getLang('static.ok'),
                                    btnClass: 'btn-primary',
                                    action: function() {
                                        // self.removeSelfFromZr();
                                    }
                                },
                                cancel: {
                                    text: fd.getLang('static.cancel'),
                                    btnClass: 'btn-primary'
                                }
                            }
                        });
                    }
                    //临时数据使用完毕就删除
                    this.dragTmpPoint = null;
                }
            }
            //最后一个点
            this.points.push(endPoint);

            this._initDragPoint();
        },
        //计算拖动点坐标
        _initDragPoint:function(){
            //拖动点坐标计算
            this.dragPoints=[];
            if(this.fromNode){
                this._getStartDragPoint();
            }
            else{
                this.dragPoints[0]={
                    x:this.points[0].x,
                    y:this.points[0].y
                };
            }
            this.dragPoints[0].pos = 0;
            if(this.toNode){
                this._getEndDragPoint();
            }
            else{
                this.dragPoints[1]={
                    x:this.points[this.points.length-1].x,
                    y:this.points[this.points.length-1].y
                };
            }
            this.dragPoints[1].pos = 1;
            //如果折线点等于3或者4时,在中间增加一个拖动点
            var len = this.points.length;
            if(len ==2){
                this.txtPoint = [
                    (this.points[0].x + this.points[1].x)/2,
                    (this.points[0].y + this.points[1].y)/2
                ];
            }
            else {
                if (len == 3) {
                    var w1 = Math.max(Math.abs(this.points[0].x - this.points[1].x),
                        Math.abs(this.points[0].y - this.points[1].y));
                    var w2 = Math.max(Math.abs(this.points[2].x - this.points[1].x),
                        Math.abs(this.points[2].y - this.points[1].y));
                    this.txtPoint = w1 > w2 ?
                        [
                            (this.points[0].x + this.points[1].x) / 2,
                            (this.points[0].y + this.points[1].y) / 2
                        ] :
                        [
                            (this.points[2].x + this.points[1].x) / 2,
                            (this.points[2].y + this.points[1].y) / 2
                        ];
                    // 增加两段折线拖动点
                    // 这个拖动点就是线段点折点
                    this.dragPoints[2] = {
                        x: this.points[1].x,
                        y: this.points[1].y,
                        pos: 3
                    };
                }
                else if (len == 4) {
                    this.dragPoints[2] = {
                        x: (this.points[len - 2].x + this.points[len - 3].x) / 2,
                        y: (this.points[len - 2].y + this.points[len - 3].y) / 2,
                        pos: 2
                    };
                    this.txtPoint = [
                        this.dragPoints[2].x,
                        this.dragPoints[2].y
                    ];
                    this.__drawLayer.checkLinePoint(this.dragPoints[2].x, this.dragPoints[2].y);
                }
                if(this.dragShapes.length >=2){
                    //直接给数组长度赋值,可以删除后面的值
                    if(this.dragShapes.length >2){
                        this.zrGroup.remove(this.dragShapes[2]);
                    }
                    this.dragShapes.length = 2;
                    //增加拖动点
                    this._makeCircleShape(this.dragPoints[2]);
                    this.zrGroup.add(this.dragShapes[2]);
                }
            }
            this.txtOnRoute = this.points[0].x < this.points[len-1].x;
            if(this.points[0].x == this.points[len-1].x){
                this.txtOnRoute = this.points[0].y < this.points[len-1].y;
            }
            this.__drawLayer.refreshRect();
        },
        _makeBrokenLinePoints: function (line) {
            /*
              折线计算(使用直线外的情况),结束坐标位于中心,开始坐标在周围时的处理
              1|4|7
              2| |8
              3|6|9
          */

            if (Math.abs(line.x1 - line.x2) >= line.rectWidthCenter + 20) {
                if (line.y1 + line.rectHeight <= line.y2) {
                    //九宫格的1区(左上) 7区右上
                    this._makeBrokenLinePoints_crose_up(line);
                }
                else if (line.y1 >= line.y2 + line.rectHeight) {
                    //九宫格的3区(左下) 9区(右下)
                    this._makeBrokenLinePoints_crose_down(line);
                }
                else {
                    //九宫格的2区(左中) 8区(右中)
                    this._makeBrokenLinePoints_middle(line);
                }
            }
            else {
                this._makeBrokenLinePoints_center(line);
            }
        },
        _makeBrokenLinePoints_crose_up:function(line){
            //一个折点时,中间折点坐标(横折)
            this.points.push({
                x:line.x2 + line.rectWidthCenter,
                y:line.y1 + line.rectHeightCenter
            });
        },
        _makeBrokenLinePoints_crose_down:function(line){
            //一个折点时,中间折点坐标(竖折)
            this.points.push({
                x:line.x1 + line.rectWidthCenter ,
                y:line.y2 + line.rectHeightCenter
            });
        },
        _makeBrokenLinePoints_middle:function(line){
            //竖横竖
            var yy = Math.min(line.y1,line.y2) - line.minHeight;//line.rectHeightCenter;
            if(yy <3){
                //自动计算横线yy已经超出上边界时,修正方向为下方
                yy = Math.max(line.y1,line.y2)  + line.rectHeight + 10 + line.minHeight;//line.rectHeightCenter;
            }
            this.points.push({
                x: line.x1 + line.rectWidthCenter,
                y: yy
            });

            this.points.push({
                x:line.x2 + line.rectWidthCenter,
                y:yy
            });
        },
        _makeBrokenLinePoints_center:function(line){
            //横竖横
            var xx = Math.max(line.x1,line.x2) + line.rectWidth + line.minWidth;//line.rectWidthCenter;
            this.points.push({
                x:xx,
                y:line.y1 + line.rectHeightCenter
            });
            this.points.push({
                x:xx,
                y:line.y2+ line.rectHeightCenter
            });
        },
        //获取开始节点出口线与节点图片的交点,用于确定拖动点
        _getStartDragPoint: function() {
            var node = this.fromNode;
            var inter = this._getLineToNodeIntersection([this.points[1].x, this.points[1].y],
                    [this.points[0].x, this.points[0].y], node.imageWidth/2,node.imageHeight/2);
            this.dragPoints[0] = {
                x: inter[0],
                y: inter[1]
            };
        },
        //获取结束节点的入口线与节点图片的交点,用于确定拖动点
        _getEndDragPoint: function() {
            var index = this.points.length - 1,
                node = this.toNode,
                inter = this._getLineToNodeIntersection([this.points[index-1].x, this.points[index-1].y],
                    [this.points[index].x, this.points[index].y], node.imageWidth/2,node.imageHeight/2);
            this.dragPoints[1] = {
                x: inter[0],
                y: inter[1]
            };
        },

        //线与节点的交点计算,用于计算箭头的开始位置
        _getLineToNodeIntersection: function(start, end, width,height) {
            var x1 = start[0], y1 = start[1], x2 = end[0], y2 = end[1];
            //计算相交点的位置
            var x=0,y=0;
            var xp=0,yp=0;

            xp = x2-(x1+x2)/2;
            yp = y2-(y1+y2)/2;

            if(x1 == x2 ){
                x = x2;
                y = y2 + height* (y1 < y2 ?-1:1) ;
            }
            else if (y1 == y2){
                x = x2 + width * (x1 > x2 ?1:-1);
                y = y2;
            }
            else if(Math.abs((y2-y1)/(x2-x1))>= height/width){
                x = x2 -Math.abs(height*(x2-x1)/(y2-y1))*(x1>x2?-1:1);
                y = y2 -height*(y1>y2?-1:1);
            }
            else{
                x = x2 - width*(x1>x2?-1:1);
                y = y2 - Math.abs(width*(y2-y1)/(x2-x1))*(y1>y2?-1:1);
            }

            return [x, y];
        },
        //点击路由开始节点
        setFrom: function(node) {
            this.fromNode = node;
            node.putRoute(this);
            node.addNodeOutRoute(this);
            this.x1 = node.x;
            this.y1 = node.y;
        },
        //点击路由结束节点
        setTo: function(node) {
            this.toNode = node;
            node.putRoute(this);
            this.x2 = node.x;
            this.y2 = node.y;
            //变更指向节点数据
            this.data.nodeId = node.id;
            this.data.nodeName = node.name;
        },
        //更改路由指向节点时
        _chgLineNode:function(dragShape,x,y){
            // console.log(this.name +"拖动点被点击");
            var route = this,
                index = $.inArray(dragShape, route.dragShapes);
            if (dragShape.invisible) { //在不显示的时候触发的事件
                route._clickLine();
            }
            else {
                if (index == 0) {
                    if (route.fromNode) {
                        route.tmpNode = route.fromNode;
                        route.tmpNode.delNodeOutRoute(route);//从数据中删除出口路由
                        route.tmpNode.removeRoute(route);    //从对象中删除当前路由关联

                        route.fromNode = null;
                    }
                    route.x1 = x - 4;
                    route.y1 = y - 4;
                    route.__Flowdesigner.dragLineHandler = route;
                }
                else if (index == 1) {
                    if (route.toNode) {
                        route.tmpNode = route.toNode;
                        route.tmpNode.removeRoute(route);    //从对象中删除当前路由关联
                        route.toNode = null;
                    }
                    route.x2 = x - 4;
                    route.y2 = y - 4;
                    route.__Flowdesigner.dragLineHandler = route;
                }
            }
        },
        //两段折线,方向调整
        _chgLineDirector:function(dragShape,x,y){
            if(this.points[1].x == this.points[0].x){
                //竖折,变成横折
                this.points[1].x = this.points[2].x;
                this.points[1].y = this.points[0].y;
            }
            else{
                //横折,变成竖折
                this.points[1].x = this.points[0].x;
                this.points[1].y = this.points[2].y;
            }

            this.refresh(false);
        },
        //拖动中间的点移动折线时
        _dragLinePoint:function(dragShap,x,y){
            // console.log(this.name +"拖动点移动中....");
            var route = this;
            //var index = $.inArray(dragShap, route.dragShapes);
            //if (index == 2) {
            //     if (!dragShap.invisible) {
                    // 如果两个节点的图形大小不一致时怎么计算????
                    var rectWidth = route.fromNode.imageWidth,
                        rectHeight = route.fromNode.imageHeight,
                        rectWidthCenter = rectWidth/2,
                        rectHeightCenter = rectHeight/2;
                    //中间点拖动处理,
                    if (route.points[1].x == route.points[2].x) {
                        //左右移动时,如果在两个节点间时,修改为默认值
                        var dx = Math.max(route.x1,route.x2) + rectWidth + rectWidthCenter;
                        if(x < dx && x + rectWidthCenter > Math.min(route.x1,route.x2)){
                            x = dx;
                        }
                        if(x < route.__drawLayer.rectMargin){
                            x = route.__drawLayer.rectMargin;
                        }
                        route.points[1].x = x;
                        route.points[2].x = x;
                    }
                    else {
                        var dy = Math.min(route.y1,route.y2) - rectHeightCenter;
                        if(y > dy && y < Math.max(route.y1,route.y2) + rectHeight + rectHeightCenter){
                            y = dy;
                        }
                        if(y < route.__drawLayer.rectMargin){
                            y = route.__drawLayer.rectMargin;
                        }
                        route.points[1].y = y;
                        route.points[2].y = y;
                    }
                // }
                route.refresh(false);
            //}
        },

        recoveNode:function(refresh){
            //恢复路由的临时节点
            if(this.fromNode){
                this.setTo(this.tmpNode);
                this.fromNode.addNodeOutRoute(this);//需要更新指向节点名称
            }
            else {
                this.setFrom(this.tmpNode);
                // this.tmpNode.addNodeOutRoute(this);
            }
            this.tmpNode = null;
            if(refresh){
                this.refresh();
            }
        },
        //对象都已经创建的情况下,移动时的刷新处理
        refresh: function(init) {
            var self = this;
            if(this.lineType == -1){
                return;
            }
            if(init == undefined){
                this._initPoint();
                var oldPoint = this.map.point;
                this.map.point = null;
            }
            else{
                this._initDragPoint();
                this.map.point = this.dragPoints[2];
            }

            var pointArray = [];
            $.each(this.points || [], function(i, point) {
                pointArray.push([point.x, point.y]);
            });
            this.lineShape.setShape({
                points: pointArray
            });
            this.arrowShape.setShape({
                points: self._getArrowPoints(pointArray)
            });

            if (this._showTypeisDesigner()) {
                //删除图标更新
                this.deleteShape.attr('style', {
                    x: this.deletePoint[0],
                    y: this.deletePoint[1]
                });

                $.each(this.dragPoints || [], function (i, circle) {
                    // console.log("拖动点:x="+circle.position.x+",y="+circle.position.y);
                    self.dragShapes[i].position = [0, 0];
                    self.dragShapes[i].setShape({
                        cx: self.dragPoints[i].x,
                        cy: self.dragPoints[i].y
                    });
                });
                if(this.dragShapes.length >2) {
                    var ignore = this.dragShapes[0].ignore;
                    if(ignore){
                        this.dragShapes[2].hide();
                    }
                    else{
                        this.dragShapes[2].show();
                    }
                }
            }
            this._setName();

            //更新数据
            this._reviewMap();
        },
        //图形数据修改
        _reviewMap:function(){
            this.map.x1 = this.x1;
            this.map.y1 = this.y1;
            this.map.x2 = this.x2;
            this.map.y2 = this.y2;
            this.map.point = this.dragPoints.length ==3? this.dragPoints[2]:null;
            if(this.fromNode){
                this.map.from = this.fromNode.id;
            }
            if(this.toNode){
                this.map.to = this.toNode.id;
            }

        },

        //绘制路由对象
        _setShape: function() {
            var self = this;
            this._initPoint();
            var pointArray = [];
            $.each(this.points || [], function(i, point) {
                pointArray.push([point.x, point.y]);
            });

            this._makeLineShape(pointArray);
            this._makeArrowShape(pointArray);
            this._makeTxtShape();
            if (this._showTypeisDesigner()) {
                this._makeDragShapes();
                this._makeDeleteShape();
            }
        },
        //增加图形到画布上
        addSelfToZr: function(init) {
            var  self = this;
            if(init == undefined){
                this._setId();
                this.map = {
                    id:this.id,
                    name:this.name,
                    lineType:this.lineType
                };

                this._reviewMap();
                //路由的定义数据,是放在开始节点中的,在最后时进行处理

                this.data['id'] = this.id;
                this.data['name'] = this.name;

                this._addLineToData();
            }
            else{
                this._setName();
            }
            this.zrGroup = new zRender.Group();
            this.zrGroup.add(this.lineShape);
            this.zrGroup.add(this.arrowShape);
            this.zrGroup.add(this.txtShape);

            if (this._showTypeisDesigner()) {
                $.each(this.dragShapes || [], function (i, dragShape) {
                    self.zrGroup.add(dragShape);
                });
                this.zrGroup.add(this.deleteShape);
            }

            this._addLineToLayer();

            if(this.fromNode) {
                this.fromNode.putRoute(this);
            }
            if(this.toNode) {
                this.toNode.putRoute(this);
            }
        },
        //删除路由
        removeSelfFromZr: function() {
            this.lineType =-1;
            if(this.fromNode) {
                //从节点数据中删除
                this.fromNode.delNodeOutRoute(this);
                this.fromNode.removeRoute(this);
            }
            if(this.toNode) {
                this.toNode.removeRoute(this);
            }

            //从MapData中删除
            this._delLineFromLayerAndData();
        },
        //添加路由到图层
        _addLineToLayer:function(){
            this.__drawLayer._routes[this.id]=this;
            this.__drawLayer.zrGroup.add(this.zrGroup);
        },
        //添加路由数据
        _addLineToData:function(){
            //data信息包含在节点中
            this.__drawLayer.data.mapData.routeNum = this.__drawLayer.routeMax;
            this.__drawLayer.data.mapData.lines[this.id] = this.map;
        },
        //删除路由图形和数据
        _delLineFromLayerAndData:function(){
            //删除一定是同时删除,但是添加不一定是同时的(添加可能不需要往mapdata中增加,比如恢复数据时)
            this.__drawLayer.zrGroup.remove(this.zrGroup);
            delete this.__drawLayer._routes[this.id];
            delete this.__drawLayer.data.mapData.lines[this.id];
        },
        //删除点击
        _deleteClick:function(){
            var self = this;
            var fd = self.__Flowdesigner;
            $.confirm({
                title: fd.getLang('static.warning'),
                content: fd.getLang('static.delrouter').replace('name',self.name),
                type: 'red',
                icon: 'glyphicon glyphicon-question-sign',
                buttons: {
                    ok: {
                        text: fd.getLang('static.ok'),
                        btnClass: 'btn-primary',
                        action: function() {
                            self.removeSelfFromZr();
                        }
                    },
                    cancel: {
                        text: fd.getLang('static.cancel'),
                        btnClass: 'btn-primary'
                    }
                }
            });
        },
        //右键菜单显示
        _showContextMenu:function(param){
            // console.log(this.name +',右键菜单');
            var para = {};
            para.left = param.event.zrX;
            para.top = param.event.zrY;
            para.items = [
                {
                    text: this.__Flowdesigner.getLang('menu.routerpro'),//路由属性
                    target:this,
                    fun: '_showProperties',
                    para: 1
                },
                {
                    text:'-',
                    enable:false
                },
                {
                    text: this.__Flowdesigner.getLang('menu.delrouter'),//'删除此路由',
                    target:this,
                    fun: '_deleteClick',
                    para: 2
                }
            ];
            para.event = param;
            para.layer = this.__drawLayer;
            this.__Flowdesigner.showContextMenu(para);
        },

        //==============================================
        //显示属性框
        _showProperties: function () {
            this.__Flowdesigner.getLineProperties().showProperties(this);
        }
    };

    return FlowLine;
});
/**
 * 流程节点对象
 * @author liys 201903
 */
define('flowdesigner/element/FlowNode',['require','jquery','zrender','./FlowLine','./FlowInit'],function (require) {
    

    var $ = require('jquery'),
        zRender = require('zrender'),
        Route = require('./FlowLine'),
        FlowInit = require('./FlowInit');

    var FlowNode = function (opts) {
        var self = this;
        for (var name in opts) {
            this[name] = opts[name];
        }
        this._setShape();
    };

    FlowNode.prototype = {
        constructor: FlowNode,
        __Flowdesigner: null,       //主对象
        __drawLayer: null,          //节点所在层对象

        id: null,   //节点id
        name: null,  //节点名称
        sortNum: 0,  //排序序号
        nodetype: null, //节点类型

        x: 0,       //节点顶点x坐标
        y: 0,       //节点顶点y坐标

        data: {},       //节点属性信息
        map: {},        //节点图形信息

        imageWidth: 50, //节点显示图片的宽度(跟图片相关,固定值)
        imageHeight: 50,//节点显示图片的高度(跟图片相关,固定值)

        zrGroup: null,  //节点显示对象组(节点相关的所有图形对象多放在此组内,便于管理)
        routes: null,   //节点相关的路由对象
        nodeShape: null,    //节点主对象
        deleteShape: null,  //删除点对象
        instanceNumShape: null, //流程监控图上显示节点数据的对象
        dragFlag: false,//是否拖动结束

        //节点id初始化(不可修改值)
        _setId: function () {
            if (this.id == 'Start') {
                this.sortNum = 0;
            } else {
                this.sortNum = this.__drawLayer.nodeMax;
                this.id += this.sortNum;
                this.name += this.sortNum;
                this._setName();
                this.__drawLayer.nodeMax++;
            }
        },
        //节点名称,根据节点名称长度进行处理
        _setName: function () {
            // var name = "一二三四五六七八九十一";//this.name;
            this.nodeShape.attr("style", {
                truncate: {
                    outerWidth: this.imageWidth + this._getOptions('nodeNameWidth')
                },
                text: this.name
            });
        },
        //初始化节点显示对应
        _setShape: function () {
            var self = this;
            this._chgMinPoint();//用来纠正节点坐标位置
            this.nodeShape = this.makeNodeShape();
            this.bindEvent(this.nodeShape);
            //1=设计/2=流程跟踪图/3=监控图/4=自动测试/5=实例修改
            switch (this.__Flowdesigner.showtype) {
                case 1:
                case 5:
                    var opts = this.__Flowdesigner.options;
                    this.deleteShape = new zRender.Image({
                        __node: self,
                        z: self.__drawLayer.getZLevel(self.__Flowdesigner.zArr.selected),
                        position: [self.x, self.y],
                        style: {
                            x: this.imageWidth - 2,
                            y: -8,
                            image: opts.imgBasePath + opts.flownode.image['deleteurl'],
                            width: 13,
                            height: 11
                        },
                        onclick: function (param) {
                            // console.log(this.name + '要删除了哦');
                            self._deleteClick();
                        }
                    });
                    this.deleteShape.hide();
                    break;
                case 2:
                case 4:
                case 6:
                    if (this.data && this.data.isCur) {
                        this.drawNowFlight('now');
                    }
                    break;
                case 3:
                    this._setShape_Monitor();
                    break;
            }

            this.setShapeExtend();
        },
        //纠正节点顶点坐标值,主要是在有泳道的情况下,避免节点放在泳道名称栏里
        _chgMinPoint: function () {
            var newPoint = this._getMinPoint([this.x, this.y]);
            this.x = newPoint[0];
            this.y = newPoint[1];
        },
        //显示流程监控图时,用来显示节点数据对象创建
        _setShape_Monitor: function () {
            var self = this;
            //监控视图,需要创建一个显示数字的小方框
            var text = '', color = ['#1fb5eb', '#ee0804'], width = 22;
            //从数据中获取颜色
            if (self.__drawLayer.data['instanceNums']['sumnumcolor']) {
                color[0] = self.__drawLayer.data['instanceNums']['sumnumcolor'];
            }
            if (self.__drawLayer.data['instanceNums']['warnnumcolor']) {
                color[1] = self.__drawLayer.data['instanceNums']['warnnumcolor'];
            }
            //创建2个小方块
            this.instanceNumShape = [];

            var makePara = function () {
                return {
                    z: self.__drawLayer.getZLevel(self.__Flowdesigner.zArr.selected),
                    position: [self.x, self.y],
                    style: {
                        opacity: 1,
                        lineWidth: 1,
                        fill: color[0],
                        stroke: color[0],
                        strokeNoScale: true, //描边粗细不随缩放而改变，false 则会根据缩放同比例缩放描边粗细。
                        transformText: true, //文字是否跟随变换效果，仅对 Path 或 Image 元素有效
                        text: text,
                        textFill: '#FFF',
                        textAlign: 'center',
                        textVerticalAlign: 'middle'
                    },
                    shape: {
                        x: self.imageWidth - 2,
                        y: -8,
                        width: width,
                        height: 15
                    }
                }
            };

            //右上角
            this.instanceNumShape.push(new zRender.Rect(makePara()));

            //右下角
            var para = makePara();
            para['shape']['y'] = self.imageHeight - 12;
            para['style']['fill'] = color[1];
            para['style']['stroke'] = color[1];
            this.instanceNumShape.push(new zRender.Rect(para));

            //绑定事件
            $.each(this.instanceNumShape, function (i, rect) {
                rect.on('click', function () {
                    self._showMonitorData(i);
                });
            })

            if (this.data) {
                $.each(['sumnum', 'warnnum'], function (i, key) {
                    text = (self.data[key] || 0) + "";
                    color = null;
                    width = null;
                    //如果是多个数字时的处理
                    if (text.length > 3) {
                        width = text.length * 8;
                    }
                    self._chgInstanceNum(i, text, color, width);
                })
            } else {
                $.each(self.instanceNumShape, function (i, rect) {
                    rect.hide();
                })
            }
        },

        _chgInstanceNum: function (pos, text, color, width) {
            var rect = this.instanceNumShape[pos];
            if (rect) {
                if (text == '' || text == '0') {
                    rect.hide();
                } else {
                    var obj = {
                        style: {
                            text: text
                        }
                    };
                    if (color) {
                        obj['style']['fill'] = color;
                        obj['style']['stroke'] = color;
                    }
                    if (width) {
                        obj['shape'] = {width: width};
                    }
                    rect.attr(obj);
                    rect.show();
                }
            }
        },

        chgInstanceNum: function (num, warn) {
            this._chgInstanceNum(0, num);
            if (warn) {
                this._chgInstanceNum(1, warn);
            }
        },
        _getLang: function (key) {
            return this.__Flowdesigner.getLang(key);
        },
        _showMsg: function (msg, title, callback) {
            return this.__Flowdesigner.showMsg(msg, title, callback);
        },
        _getOptions: function (key) {
            return this.__Flowdesigner.getOptions(key);
        },
        //点击小方框时触发
        _showMonitorData: function (pos) {
            var self = this;
            //调用外部接口实现监控实例的展示
            try {
                //外部方法,用于替换点击事件
                if (gMonitorClick(this.__drawLayer.flowid, this.id, pos)) {
                    return;
                }
            } catch (e) {

            }
            //从后台获取数据,并展示到表格中
            this.__Flowdesigner.loadWorksByNodeid(this.__drawLayer.flowid, this.id, pos, function (works) {
                if (works && works.length > 0) {
                    var html = '<table id="popSel" />';

                    self.__Flowdesigner.popSelWin(
                        self._getLang('static.instances').replace('name', self.name),
                        html,
                        function ($this) {

                        },
                        '550px', null, function ($this) {
                            $this.$contentPane.css('max-height', '450px');
                            var tableHead = function () {
                                var title = self._getLang('table.monitor.title');
                                return [
                                    {
                                        title: title[0],//'标题',
                                        name: 'title',
                                        width: 500,
                                        lockWidth: false,
                                        align: 'left',
                                        renderer: function (val, item, rowIndex) {
                                            var url = self._getOptions('testFlowPage')
                                                + '?workId=' + item['workid']
                                                + '&trackId=' + item['trackid'];

                                            return '<a href="' + url + '" target="_blank">' + val + '</a>';
                                        }
                                    }
                                ];
                            };
                            var items = works || [];
                            var tblObj = $this.$content.find('#popSel').mmGrid({
                                height: 350
                                ,delTitle:self._getLang('table.field.defTitle')
                                ,showCol:self._getLang('table.field.showCol')
                                , cols: tableHead()
                                , items: items      //本地数据

                                , multiSelect: false
                                , fullWidthRows: true
                                , autoLoad: false
                                , loadingText: self._getLang('table.monitor.load') //'正在加载实例列表...'
                                , noDataText: self._getLang('table.monitor.nodata') //'当前无记录'
                            });
                            tblObj
                                .on('cellSelected', function (e, item, rowIndex, colIndex) {

                                })
                                .load();
                        });
                } else {
                    //TODO 子流程节点的数字点击处理
                    if (self.nodetype == self.__Flowdesigner.options.nodetype['Node_Sub']['data']) {
                        self.showSubFlow();

                    } else {
                        self.__Flowdesigner.showMsg(self._getLang('table.monitor.noinstance'));
                    }
                }
            });
        },

        //节点对象主图形创建,子类可能会重写的类(主要是子流程节点会重写)
        makeNodeShape: function () {
            var self = this;
            var showtype = this.__Flowdesigner.showtype;
            return new zRender.Image({
                __node: this,
                z: self.__drawLayer.getZLevel(self.__Flowdesigner.zArr.node),
                scale: [1, 1],  //缩放比例
                origin: [0, 0], //设置缩放中心
                position: [self.x, self.y],
                style: {
                    x: 0,
                    y: 0,
                    strokeNoScale: true, //描边粗细不随缩放而改变，false 则会根据缩放同比例缩放描边粗细。
                    transformText: true, //文字是否跟随变换效果，仅对 Path 或 Image 元素有效
                    image: self._getImgPath(false),
                    width: self.imageWidth,
                    height: self.imageHeight,
                    text: self.name,
                    textPosition: 'bottom',
                    textAlign: 'center'
                },
                draggable: (showtype == 1 || showtype == 5)

            });
        },
        //绑定事件
        bindEvent: function (objCanvas) {
            var self = this;
            // 1=设计/2=流程跟踪图/3=监控图/4=自动测试/5=实例修改
            switch (this.__Flowdesigner.showtype) {
                case 1:
                case 5:
                    objCanvas
                        .on('mouseover', function (param) {
                            if (!self.dragFlag) {
                                self._chgForMouseover();
                            }
                        })
                        .on('mouseout', function (param) {
                            self._chgForMouseout();
                        })
                        .on('mousedown', function (param) {
                            //右键禁止拖动
                            if (param.event.button == 0) {
                                objCanvas.draggable = true;
                            } else {
                                objCanvas.draggable = false;
                            }
                        })
                        .on('click', function (param) {
                            // console.log(self.name + "节点被点击");
                            self._onclick(param);
                        })
                        .on('drag', function (param) {
                            // console.log(self.name + "节点移动中...");
                            self._ondrag(param);
                        })
                        .on('dragend', function () {
                            self.dragFlag = false;
                        })
                        .on('contextmenu', function (param) {
                            // console.log(self.name + '右键菜单');
                            self._showContextMenu(param);
                            return false;
                        });
                    break;
                case 2:
                    objCanvas.on('click', function (param) {
                        // console.log(self.name + "节点被点击");
                        self._showHistory(param);
                    });
                    break;
                case 3:
                    objCanvas.on('click', function (param) {
                        // console.log(self.name + "节点被点击");
                        self.showSubFlow(param);
                    });
                    break;
                case 4:
                    objCanvas.on('click', function (param) {
                        // console.log(self.name + "节点被点击");
                        self.autoTest(param);
                    });
                    break;
            }

            objCanvas
                .on('mouseover', function (param) {
                    if (!self.dragFlag) {
                        self.__Flowdesigner.showTitle(self.name + "[" + self.id + "]",
                            {x: param.event.zrX, y: param.event.zrY});
                    }
                })
                .on('mouseout', function (param) {
                    self.__Flowdesigner.hideTitle();
                });
        },
        _chgForMouseover: function () {
            if (this.__Flowdesigner.selNodeHandler != this) {
                this.chgNodeShapeForClick(true);
            }
            this._chgForMousemove(true);
        },
        _chgForMouseout: function () {
            if (this.__Flowdesigner.selNodeHandler != this) {
                this.chgNodeShapeForClick(false);
            }
            this._chgForMousemove(false);
        },
        _chgForMousemove: function (over) {
            this.nodeShape.attr({
                z: this.__drawLayer.getZLevel(this.__Flowdesigner.zArr.node + (over ? 1 : 0)),
                style: {
                    shadowBlur: over ? 5 : 0,
                    shadowColor: this.__Flowdesigner.options.flownode.color.done
                }
            });
        },


        //自动测试的时候,根据流程运转情况进行图形演示标记区分使用
        chgNodeShapeForTest: function (showtype, nodetype) {
            var url = this._getImgPath(null, showtype, nodetype);

            this.nodeShape.attr({
                style: {
                    image: url
                }
            });

            this.closeFlight();

        },
        //获取节点图片类型
        _getImgShowtype: function (sel) {
            var imgShowtype = 'defurl';
            if (sel) {
                imgShowtype = 'doneurl';
            } else if (this.__Flowdesigner.showtype == 2 || this.__Flowdesigner.showtype == 6) {
                //流程跟踪时
                if (this.data && this.data.showtype) {
                    imgShowtype = this.data.showtype;
                }
            }
            return imgShowtype;
        },
        //获取主图形对应的图片
        _getImgPath: function (sel, showtype, nodetype) {
            var fd = this.__Flowdesigner;
            var name = "00" + (nodetype ? nodetype : this.nodetype);
            name = name.substring(name.length - 3);

            var path = fd.options.flownode.image[showtype ? showtype : this._getImgShowtype(sel)];

            var url = fd.options.imgBasePath + path + name + (this.map['subflow'] ? 's' : '') + ".png";
            return url;
        },
        //点击事件处理
        _onclick: function (param) {
            if (this.__drawLayer.isScale()) {
                return;
            }
            var fd = this.__Flowdesigner;
            if (fd.startSelArea) {
                //拖动结束点移动到节点上时,不触发节点的click事件
                return;
            }
            fd.cancelSel();
            if (this.dragFlag) {
                this.dragFlag = false;
                return;
            }
            // //当前节点标记被选中
            if (fd.dragLineHandler) {
                //结束线条
                this._doEndFlowLine(param);
            } else if (fd.ckLineObj) {
                //开始画线
                this._createFlowLine(param);
            } else {
                this._ckSeleted();
            }
        },
        //拖动节点处理
        _ondrag: function (param) {
            var fd = this.__Flowdesigner;
            if (this.__drawLayer.isScale()) {
                this.nodeShape.attr({position: [this.x, this.y]});
                this.chgRelationExtend();
                return;
            }
            // console.log(this.name+"拖动中...");
            fd.cancelSel();
            fd.hideProperties();

            var clientWidth = fd.zrender.getWidth() - this.imageWidth - 20;
            var clientHeight = fd.zrender.getHeight() - this.imageHeight - 40;

            var point = this.getDragPoint();
            //获取上面和左面位置的最小值
            var minPoint = this._getMinPoint(point);

            var x = minPoint[0];
            var y = minPoint[1];
            //x = Math.min(x, clientWidth);
            //y = Math.min(y, clientHeight);

            if (Math.abs(this.x - x) > fd.nodemove || Math.abs(this.y - y) > fd.nodemove) {
                // console.log('节点拖动超过5,移动');
                this.x = x;
                this.y = y;
                this.nodeShape.attr({position: [this.x, this.y]});
                this._chgRelation();
                this.dragFlag = true;
            } else {
                // console.log('节点拖动小于5,不移动,避免误点时,已经拖动的线条会重新计算');
                this.nodeShape.attr({position: [this.x, this.y]});
            }
        },
        //获取拖动后,节点对应的位置信息
        getDragPoint: function () {
            return this.nodeShape.position;
        },
        //节点坐标变化时,对图形进行更新处理(比如拖动时)
        _chgRelation: function () {
            this._reviewMap();
            this.chgRelationExtend();
            $.each(this.routes || [], function (routeId, route) {
                route.refresh();
            });
            //刷新层的包围矩形
            this.__drawLayer.chgForShapeDrag(this.x, this.y);
        },
        //获取在有无泳道的情况下,节点的顶点能到达的极限位置
        _getMinPoint: function (point) {
            return this.__drawLayer.getMinPoint(point);
        },
        //更新节点位置信息(map数据中的信息)
        _reviewMap: function () {
            this.map.x = this.x;
            this.map.y = this.y;
        },
        //创建一条新路由
        _createFlowLine: function (param) {
            var fd = this.__Flowdesigner;
            //开始,事件,自动,交互,虚拟 只能创建一条出口路由
            if ((this.isOnlyOneRoutNode() && !$.isEmptyObject(this.routes))
                || (this.isOnlyOneOutRouteNode() && this.isHaveOneOutRoute())
            ) {
                $.confirm({
                    title: fd.getLang('static.info'),
                    content: fd.getLang('static.startOnly'),
                    type: 'blue',
                    icon: 'glyphicon glyphicon-info-sign',
                    buttons: {
                        ok: {
                            text: fd.getLang('static.ok'),
                            btnClass: 'btn-primary'
                        }
                    }
                });
                return;
            }
            if (this.isEndNode()) {
                $.confirm({
                    title: fd.getLang('static.info'),
                    content: fd.getLang('static.endRoute'),
                    type: 'blue',
                    icon: 'glyphicon glyphicon-info-sign',
                    buttons: {
                        ok: {
                            text: fd.getLang('static.ok'),
                            btnClass: 'btn-primary'
                        }
                    }
                });
                return;
            }
            //当前画布被拖动时,需要增加位移
            var mPoint = this.__drawLayer.zrGroup.position;
            var route = new Route({
                __Flowdesigner: fd,
                __drawLayer: this.__drawLayer,
                // from:this.id,    //不在此赋值,而在下面使用setFrom(为了保证路由相关设置操作,由路由对象执行)
                lineType: fd.ckLineType, //路由类型,1直线,2折线
                x1: this.x + this.imageWidth / 2,
                y1: this.y + this.imageHeight / 2,

                x2: param.event.zrX - mPoint[0],
                y2: param.event.zrY - mPoint[1],

                data: FlowInit.initRoute(),

                name: fd.options.language.parts['route']
            });
            //把路由对象添加到画布中,同时对id进行编号
            route.addSelfToZr();
            //设置开始节点对象
            route.setFrom(this);
            //标记当前选中的路由对象
            fd.dragLineHandler = route;
        },
        //只允许一条路由
        isOnlyOneRoutNode: function () {
            return false;
        },
        //只允许一条出口路由
        isOnlyOneOutRouteNode: function () {
            return false;
        },
        //是否结束节点
        isEndNode: function () {
            return false;
        },
        //是否开始节点
        isStartNode: function () {
            return false;
        },
        //是否已经存在一条路由
        isHaveOneOutRoute: function () {
            var isHave = false;
            var self = this;
            $.each(this.routes || [], function (i, route) {
                if (route.fromNode && route.fromNode.id == self.id) {
                    isHave = true;
                    return false;
                }
            });
            return isHave;
        },
        //路由结束点确定时的处理
        _doEndFlowLine: function (param) {
            var fd = this.__Flowdesigner;
            var msg = '';
            if (fd.dragLineHandler.fromNode && fd.dragLineHandler.toNode) {
                fd.dragLineHandler = null;
                return;
            }

            if (this.isOnlyOneRoutNode()) {
                if (fd.dragLineHandler.fromNode) {
                    msg = fd.getLang('static.startRoute');
                } else if ($.isEmptyObject(this.routes)) {
                    //开始节点无路由时,判断结束点是否为结束节点
                    if (this.isStartNode() &&
                        fd.dragLineHandler.toNode && fd.dragLineHandler.toNode.isEndNode()) {
                        msg = fd.getLang('static.startToEnd');
                    }
                } else {
                    //已经有路由时
                    msg = fd.getLang('static.startOnly');
                }
            } else if (this.isEndNode()) {
                if (fd.dragLineHandler.toNode) {
                    //已经有结束点时
                    msg = fd.getLang('static.endRoute');
                } else if (fd.dragLineHandler.fromNode && fd.dragLineHandler.fromNode.isStartNode()) {
                    //开始点是否为开始节点
                    msg = fd.getLang('static.startToEnd');
                }
            } else if (fd.dragLineHandler.toNode && this.isOnlyOneOutRouteNode() && this.isHaveOneOutRoute()) {
                msg = fd.getLang('static.startOnly');
            }

            if (msg != '') {
                $.confirm({
                    title: fd.getLang('static.info'),
                    content: msg,
                    type: 'blue',
                    icon: 'glyphicon glyphicon-info-sign',
                    buttons: {
                        ok: {
                            text: fd.getLang('static.ok'),
                            btnClass: 'btn-primary'
                        }
                    }
                });
                return;
            }

            if (fd.dragLineHandler.fromNode) {
                if (fd.dragLineHandler.fromNode.id == this.id) {
                    //点击开始节点时
                    return;
                }
                fd.dragLineHandler.x2 = this.x;
                fd.dragLineHandler.y2 = this.y;
                //判断当前路由是否已经存在与结束节点
                if (this._checkLineInNode(this.routes, fd.dragLineHandler)) {
                    if (fd.dragLineHandler.tmpNode) {
                        //恢复到原来的节点上
                        fd.dragLineHandler.recoveNode(false);//最后再执行refresh
                    } else {
                        //删除当前line
                        fd.dragLineHandler.removeSelfFromZr();
                    }
                } else {
                    fd.dragLineHandler.setTo(this);
                    fd.dragLineHandler.fromNode.addNodeOutRoute(fd.dragLineHandler);
                }
            } else if (fd.dragLineHandler.toNode) {
                if (fd.dragLineHandler.toNode.id == this.id) {
                    //点击开始节点时
                    return;
                }
                fd.dragLineHandler.x1 = this.x;
                fd.dragLineHandler.y1 = this.y;
                //判断当前路由是否已经存在与结束节点
                if (this._checkLineInNode(this.routes, fd.dragLineHandler)) {
                    if (fd.dragLineHandler.tmpNode) {
                        //恢复到原来的节点上
                        fd.dragLineHandler.recoveNode(false);//最后再执行refresh
                    } else {
                        //删除当前line
                        fd.dragLineHandler.removeSelfFromZr();
                    }
                } else {
                    fd.dragLineHandler.setFrom(this);
                    // this.addNodeOutRoute(fd.dragLineHandler);
                }
            }
            fd.dragLineHandler.refresh();
            fd.dragLineHandler = null;
        },
        //判断是否已经存在
        _checkLineInNode: function (routes, line) {
            var result = false;
            $.each(routes || [], function (routeId, route) {
                if (route.x1 == line.x1 && route.y1 == line.y1
                    && route.x2 == line.x2 && route.y2 == line.y2) {
                    result = true;
                    return false;
                }
            });

            return result;
        },
        //取消节点选中状态
        cancelSel: function () {
            this.chgNodeShapeForClick(false);

            this.deleteShape.hide();
            this.__Flowdesigner.selNodeHandler = null;
        },
        //修改节点是否被选中的状态处理
        chgNodeShapeForClick: function (selected) {
            this.nodeShape.attr({
                z: this.__drawLayer.getZLevel(this.__Flowdesigner.zArr.node + (selected ? 1 : 0)), //加1是为了有重叠的时候,能把选中的显示在上面
                style: {
                    image: this._getImgPath(selected)
                }
            });
        },
        //点击节点时的处理
        _ckSeleted: function () {
            this.chgNodeShapeForClick(true);
            this.__Flowdesigner.selNodeHandler = this;

            //显示删除图标
            if (this.isStartNode()) {
                return;
            }
            this.deleteShape.attr({
                position: this.nodeShape.position
            });
            this.deleteShape.show();
        },
        //拖动选择多个节点时
        dragSelected: function (show) {
            this.chgNodeShapeForClick(show);
        },
        //多个节点对齐
        alignNode: function (isH, pos) {
            if (isH) {
                this.x = pos;
            } else {
                this.y = pos;
            }
            this._chgNodePos();
        },
        //节点位置移动(修改坐标值,并更新对应的图形显示)
        //用于节点已经存在,后创建泳道时,对已有节点进行处理
        moveNode: function () {
            var minPoint = this._getMinPoint([this.x, this.y]);
            var x = minPoint[0];
            var y = minPoint[1];
            this.x = x;
            this.y = y;
            this._chgNodePos();
        },
        //根据偏移量x,y，移动节点
        posNode: function (x, y) {
            this.x = this.x + x;
            this.y = this.y + y;
            this._chgNodePos();
        },
        //节点x，y发生变化时，节点图形的变化处理
        _chgNodePos: function () {
            this.nodeShape.attr({position: [this.x, this.y]});
            this._chgRelation();
        },

        //删除节点,点击事件
        _deleteClick: function () {
            var self = this;
            var fd = self.__Flowdesigner;
            $.confirm({
                title: fd.getLang('static.warning'),
                content: fd.getLang('static.delnode').replace('name', self.name),
                type: 'red',
                icon: 'glyphicon glyphicon-question-sign',
                buttons: {
                    ok: {
                        text: fd.getLang('static.ok'),
                        btnClass: 'btn-primary',
                        action: function () {
                            self.removeSelfFromZr();
                        }
                    },
                    cancel: {
                        text: fd.getLang('static.cancel'),
                        btnClass: 'btn-primary'
                    }
                }
            });
        },

        //创建节点数据,并把所有相关的图形对象放入组中
        addSelfToZr: function (init) {
            var self = this;
            if (init == undefined) {
                this._setId();
                //初始化数据对象
                this.map = {
                    id: this.id,
                    name: this.name,
                    nodeType: this.nodetype
                };
                this._reviewMap();
                this.data = FlowInit.initProcess();
                this.data.id = this.id;
                this.data.name = this.name;
                this.data.nodeType = this.nodetype;
                //三个地方需要初始化
                //1.special,2.authDo,3.participants
                this._initData_Create();

                var def = this.__Flowdesigner.getNodetypeDefinition(this.nodetype);
                this.data.className = def['className'];

                this._addNodeToData();
            } else {
                this._setName();
            }
            //图行部分增加到画布中
            this.zrGroup = new zRender.Group();
            this.zrGroup.add(this.nodeShape);

            switch (this.__Flowdesigner.showtype) {
                case 1:
                case 5:
                    this.zrGroup.add(this.deleteShape);
                    break;
                case 3:
                    $.each(this.instanceNumShape, function (i, rect) {
                        self.zrGroup.add(rect);
                    });

                    break;
            }

            this.addSelfToZrExtend();

            this._addNodeToLayer();
        },
        _initData_Create: function () {
            var self = this;
            var participantsName = self.__Flowdesigner.options.participantsName;
            //participants在子类中定义
            var defMsgSel = self.__Flowdesigner.options['defSendMsg'] || '';
            $.each(this.participants || [], function (i, participant) {
                var newParticipant = FlowInit.initAuth();
                newParticipant['authId'] = participant;
                newParticipant['authName'] = participantsName[participant];
                //20201102 LIYS 增加默认值的赋值
                newParticipant['msgFlag'] = defMsgSel;
                self.data.participants[participant] = newParticipant;
            });

            var allForms = self.__drawLayer.data.flowInfo['forms'];//所有已经定义的表单列表
            var operators = self.__Flowdesigner.options.operators;//按钮的详细信息
            //因为表单基本在每个身份下都一样,所以不在循环中处理
            //表单 需要默认添加所有的表单
            var defId = '';
            var tmpGroup = [];
            var tmpForms = [];
            $.each(allForms || [], function (i, form) {
                if (!form) {
                    return true;
                }
                if (defId == '' && form.isMain == 1) {
                    defId = form.id;
                }
                var group = form.group;
                // 无分组             有分组            且不在临时记录中时
                if ((!group) || (group && $.inArray(group, tmpGroup) == -1)) {
                    tmpForms.push(form.id);
                    if (group) {
                        tmpGroup.push(group);//放入临时记录,避免同组的其他表单加入
                    }
                }
            });

            $.each(this.operators || [], function (i, participant) {
                var newOperator = FlowInit.initDo();
                newOperator['id'] = participant;
                //操作部分初始化
                var defActions = self.__Flowdesigner.options.defOperator[participant];//默认需要选中的按钮
                var actions = {};
                $.each(defActions, function (i, key) {
                    var ac = operators[key];
                    //还需要判断节点类型和操作是否匹配
                    if (self.checkActionShow(self.nodetype, self.getStatus(), ac['node'])) {
                        actions[key] = {
                            id: ac.id,
                            name: ac.name,
                            implClass: ac.implClass,
                            reName: ac.reName
                        };
                    }
                });
                //把按钮信息放入刚刚创建的对象中
                newOperator['buttons']['actions'] = actions;

                var forms = {};
                //表单 需要默认添加所有的表单
                $.each(tmpForms, function (i, key) {
                    var item = {
                        id: key,
                        buttons: '',
                        sort: allForms[key]['sort'],
                        fieldControlId: participant.indexOf('Author') == -1 ? 'allreadonly' : 'alleditable'
                    }
                    forms[key] = item;
                });
                newOperator['forms']['dfId'] = defId;
                newOperator['forms']['form'] = forms;

                self.data.authDo[participant] = newOperator;
            });


        },
        //从画布中删除当前节点对象,同时删除相关的路由对象
        removeSelfFromZr: function () {
            this.__Flowdesigner.delNodeRule(this.data, this.__drawLayer);
            //删除对应的路由
            $.each(this.routes || [], function (i, route) {
                route.removeSelfFromZr();
            });

            this._delNodeFromLayerAndData();
        },
        //把图形组放入层中,并缓存对象
        _addNodeToLayer: function () {
            this.__drawLayer._nodes[this.id] = this;
            this.__drawLayer.zrGroup.add(this.zrGroup);
        },
        //增加节点或者路由时,把数据增加到整体data中
        _addNodeToData: function () {
            this.__drawLayer.data.process[this.id] = this.data; //包含路由的data信息
            this.__drawLayer.data.mapData.nodes[this.id] = this.map;
            this.__drawLayer.data.mapData.nodeNum = this.__drawLayer.nodeMax;
        },
        //从画图层中删除当前节点信息,并更新数据对象
        _delNodeFromLayerAndData: function () {
            //规则数据删除
            this.__drawLayer.zrGroup.remove(this.zrGroup);
            delete this.__drawLayer._nodes[this.id];

            delete this.__drawLayer.data.process[this.id];
            delete this.__drawLayer.data.mapData.nodes[this.id];
        },
        //用于子类扩展时增加
        setShapeExtend: function () {
        },
        //用于子类扩展增加额外的对象
        addSelfToZrExtend: function () {
        },
        //拖动时刷新
        chgRelationExtend: function () {
        },

        //增加路由
        putRoute: function (line) {
            if (this.routes == null) {
                this.routes = {};
            }
            this.routes[line.id] = line;
        },
        //删除路由
        removeRoute: function (line) {
            delete this.routes[line.id];
        },
        //从路由列表中删除
        delNodeOutRoute: function (line) {
            if (this.data.transitions) {
                delete this.data.transitions[line.id];
            }
        },
        //在数据中增加路由信息
        addNodeOutRoute: function (line) {
            if (!this.data['transitions']) {
                this.data['transitions'] = {};
            }
            this.data['transitions'][line.id] = line.data;
        },
        //创建右键菜单项
        _addMenuItem: function () {
            var fd = this.__Flowdesigner;
            if (fd.showtype == 1 || fd.showtype == 5) {
                var items = [];
                if (this.nodetype != 900) {
                    this.addProMenuItem(items);
                    items.push({
                        text: '-',
                        enable: false
                    });

                    items.push(
                        {
                            text: fd.getLang('menu.import'),//从模版导入
                            target: this,
                            fun: '_importNode'
                        });
                    items.push(
                        {
                            text: fd.getLang('menu.savemodule'),//存为模版
                            target: this,
                            fun: '_saveModule'
                        });
                }
                //开始节点不能复制
                if (this.nodetype >= 10) {
                    items.push(
                        {
                            text: fd.getLang('menu.copynode'),//复制当前节点
                            target: this,
                            fun: '_copyNode'

                        });
                }
                items.push({
                    text: '-',
                    enable: false
                });
                items.push({
                    text: fd.getLang('menu.delnode'),//'删除此节点',
                    target: this,
                    fun: '_deleteClick',
                    para: 2
                });
                if (this.nodetype != 900) {
                    items.push({
                        text: '-',
                        enable: false
                    });
                    items.push(
                        {
                            text: fd.getLang('menu.showdata'),//属性设置
                            target: this.__Flowdesigner,
                            fun: 'showJsonData',
                            para: this.data
                        });
                }
                return items;
            }
            return [];
        },
        addProMenuItem: function (items) {

        },
        //接口类,用于子类实现额外的菜单项
        addOtherMenuItem: function (items) {
        },
        //显示菜单项时的数据准备,并调用主对象中的菜单显示方法
        _showContextMenu: function (param) {
            var para = {};
            para.left = param.event.zrX;
            para.top = param.event.zrY;
            para.items = this._addMenuItem();
            this.addOtherMenuItem(para.items);
            para.event = param;
            para.layer = this.__drawLayer;
            this.__Flowdesigner.showContextMenu(para,true);
            //如何阻止事件继续往上冒泡呢
            //param.preventDefault();//貌似不管用呀,暂时使用它的错误来阻止吧
            // param.cancelBubble = true; //放到this.__Flowdesigner.showContextMenu中执行
        },

        //拷贝节点
        _copyNode: function () {
            //1.拷贝数据
            var newData = JSON.parse(JSON.stringify(this.data));
            var newMap = JSON.parse(JSON.stringify(this.map));
            //2.处理数据中的内容
            //2.1 修改节点id和名称
            var maxNum = this.__drawLayer.nodeMax++;
            var newId = this._getNodeFix(this.id) + maxNum;

            newData.id = newId;
            //newData.name = this._getLang('parts.copy')+ maxNum;
            newMap.id = newId;
            //newMap.name = newData.name;
            //2.2删除路由数据
            newData.transitions = {};
            //2.3坐标数据修改,默认增加50
            newMap.x = newMap.x + 25;
            newMap.y = newMap.y + 25;
            //2.4规则内容处理
            this.__Flowdesigner.copyNodeRule(newData, this.__drawLayer, false);

            //3.创建并显示图形
            var newNode = this.__Flowdesigner.loadNode(newData, newMap, this.__drawLayer);
            newNode._addNodeToData();//把数据添加到整体数据中
        },
        _getNodeFix: function (id) {
            var fix = '';
            $.each(['Node', 'End', 'Gateway', 'Subflow', 'Event', 'Robot', 'Cluster', 'Virtual'],
                function (i, key) {
                    if (id.indexOf(key) != -1) {
                        fix = key;
                        return false;
                    }
                });
            return fix;
        },
        //从模版导入
        _importNode: function () {
            var self = this;
            var fd = self.__Flowdesigner;
            var title = self._getLang("prop.selnodemodule");//['请选择节点模版','模版数据异常','导入完毕!'];
            var nodefix = this.id.substring(0, 3);

            fd.getNodeModuleLstFromServer(nodefix, function (data) {
                var nodes = data && data.nodes || {};
                var zNodes = fd.initTreeData(nodes);
                var html =
                    '<div style="background-color: #F5F5F5">' +
                    '<ul id="tree" class="ztree" style="width:300px;height:300px; overflow:auto;"></ul></div>' +
                    '<div style="display: block;position: absolute;margin-left: 305px;top: 0px">' +
                    '<select name="moduleId" size=10 style="width:215px;height:300px;"></select>' +
                    '</div>';
                fd.popSelWin(title[0], html,
                    function ($this) {
                        var moduleId = $this.find('select[name="moduleId"]').val();
                        if (moduleId == '') {
                            self._showMsg(title[0]);
                            return false;
                        }

                        var nodeObj = nodes[moduleId];
                        if (nodeObj && nodeObj['data']) {
                            var newData = JSON.parse(nodeObj['data']);
                            if (newData) {
                                newData.id = self.data.id;
                                newData.name = self.data.name;
                                //规则处理(相当于节点拷贝处理)
                                fd.copyNodeRule(newData, self.__drawLayer, false);

                                newData.transitions = self.data.transitions;
                                delete newData['ruleId'];

                                self.data = newData;
                                self.nodetype = newData.nodeType;
                                self.map['nodeType'] = newData.nodeType;
                                // self.map['name'] = newData.name;
                                //处理子流程节点的map数据
                                self.doSubflow();
                                //同一类节点的类型变化时,图片修改
                                self.chgNodeShapeForTest('defurl');

                                self._addNodeToData();//更新到总体数据中

                                self._showMsg(title[2]);
                                return;
                            }
                        }
                        self._showMsg(title[1]);
                    },
                    '550px', null,
                    function ($this) {
                        //初始化树
                        $.fn.zTree.init($this.$content.find("#tree"), {
                            callback: {
                                onClick: function (event, treeId, treeNode) {
                                    initSelect(treeNode.data);
                                }
                            }
                        }, zNodes);
                        var initSelect = function (data) {
                            //初始化所有数据到列表中
                            var moduleId = $this.$content.find('select[name="moduleId"]');
                            moduleId.empty();
                            $.each(data || [], function (i, item) {
                                if (item) {
                                    moduleId.append('<option value="' + item.id + '">' + item.name + '</option>');
                                }
                            });
                        };
                        //默认显示全部
                        initSelect(nodes);
                    });

            });
        },
        //保存模版
        _saveModule: function () {
            var self = this;
            var fd = self.__Flowdesigner;
            fd.getNodeTypeFromServer(function (data) {
                var title = self._getLang("prop.savenodemodule");// ['请输入模版名称', '请选择模版分类', '分类(可选,多级分类时使用/分隔;双击输入框可以选择已有分类):'];
                var html = '<div id="selInput"><input class="form-control input-sm" name="nodeModule">'
                    + title[2] + '<input class="form-control input-sm" name="moduleType"></div>'

                    + '<div id="selTree" style="background-color: #F5F5F5 ;display:none" >'
                    + '<ul id="tree" class="ztree" style="width:100%;height:300px; overflow:auto;"></ul>'
                    + '</div>';
                //从后端获取模版分类
                var treeData = data['moduletype'] || [];

                fd.popSelWin(title[0], html,
                    function ($this, $content) {
                        if ($this.find('#selInput').is(":visible")) {
                            var name = $this.find('input[name="nodeModule"]').val();
                            if (name.trim() == '') {
                                self._showMsg(title[0]);
                                return false;
                            }

                            var newData = JSON.parse(JSON.stringify(self.data));
                            newData.transitions = {};//删除路由信息
                            //规则需要拷贝存储
                            var rules = fd.copyRuleModule(newData, self.__drawLayer);

                            //记录规则的id,便于删除时获取
                            var ruleId = '';
                            $.each(rules, function (i, rule) {
                                ruleId += ',' + rule.id;
                            });
                            if (ruleId != '') {
                                ruleId = ruleId.substring(1);
                            }
                            newData['ruleId'] = ruleId; //记录规则ID

                            var fix = self.id.substring(0, 3);
                            var type = $this.find('input[name="moduleType"]').val();
                            fd.saveNodeModule(name, fix, type,
                                JSON.stringify(newData),
                                JSON.stringify(rules),
                                function (data) {
                                    self._showMsg(data.msg);
                                });
                        } else {
                            var treeObj = $.fn.zTree.getZTreeObj("tree");
                            var nodes = treeObj.getSelectedNodes();
                            if (nodes.length == 0) {
                                self._showMsg(self._getLang('prop.seltype')); //'请选择分类'
                                return false;
                            }
                            var flowtype = [];
                            flowtype.push(nodes[0].name);
                            var pNode = nodes[0].getParentNode();
                            while (pNode != null) {
                                flowtype.push(pNode.name);
                                pNode = pNode.getParentNode();
                            }
                            flowtype.reverse();

                            $this.find('input[name="moduleType"]').val(flowtype.join('/'));

                            $this.find('#selInput').show();
                            $this.find('#selTree').hide();
                            $content.setTitle(title[0]);

                            return false;
                        }
                    },
                    400, null,
                    function ($this) {
                        var zNodes = fd.initTreeData(treeData, $this.$content.find('input[name="moduleType"]').val());
                        $.fn.zTree.init($this.$content.find("#tree"), {}, zNodes);
                        $this.$content.find('input[name="moduleType"]').on('dblclick', function () {
                            $this.setTitle(title[1]);
                            $this.$content.find('#selInput').hide();
                            $this.$content.find('#selTree').show();
                        })
                    }, false,
                    function ($this) {
                        if ($this.$content.find('#selTree').is(":visible")) {
                            $this.setTitle(title[0]);
                            $this.$content.find('#selInput').show();
                            $this.$content.find('#selTree').hide();
                            return false;
                        }
                    });
            });
        },
        //==============================================
        //点击节点继续自动测试提交
        autoTest: function () {
            if (this.data) {
                this.__Flowdesigner.submitToNxt(this.id);
            }
        },
        //显示节点跟踪信息
        _showHistory: function () {
            var self = this;
            //this.data.history 数组
            // if (this.data && this.data.showtype) {//有showtype,则表示当前节点可能有跟踪记录信息,否则无
                var name = this.name;
                if (name.length > 30) {
                    name = name.substring(0, 30) + '...';
                }
                this.__Flowdesigner.popSelWin(
                    self._getLang('static.nodehistory').replace('name', name),
                    '<table id="popSel" />',
                    function () {
                    },
                    '950px', null, function ($this) {
                        $this.$contentPane.css('max-height', '450px');
                        var items = self.data && self.data['history']?self.data['history'] : [];

                        self.__Flowdesigner.makeHistoryTable($this, items);
                    });
            // } else {
            //     var self = this;
            //     $.confirm({
            //         backgroundDismiss: true,//是否允许点击背景关闭
            //         title: self._getLang('static.nodehistory').replace('name', self.name),
            //         content: self._getLang('static.nohistory'),//'当前节点没有流转记录',
            //         type: 'blue',
            //         icon: 'glyphicon glyphicon-info-sign',
            //         buttons: {
            //             ok: {
            //                 text: self._getLang('static.ok'),
            //                 btnClass: 'btn-primary',
            //                 action: function () {
            //                 }
            //             }
            //         }
            //     });
            // }
        },

        test: function () {
            var html = '<div style="">';
            //单选时
            html += '<label class="radio-inline ">' +
                '<input type="radio" name="AA" value="AA1">AA1</label><br>';
            html += '<label class="radio-inline ">' +
                '<input type="radio" name="AA" value="AA2">AA2</label><br>';
            html += '<label class="radio-inline ">' +
                '<input type="radio" name="AA" value="AA3">AA3</label><br>';
            html += '<label class="radio-inline ">' +
                '<input type="radio" name="BB" value="BB1">BB1</label><br>';
            html += '<label class="radio-inline ">' +
                '<input type="radio" name="BB" value="BB2">BB2</label><br>';

            html += '<label class="checkbox-inline">' +
                '<input type="checkbox" name="CC1" value="CC1">CC1</label><br>';
            html += '<label class="checkbox-inline">' +
                '<input type="checkbox" name="DD1" value="DD1">DD1</label><br>';
            html += '<label class="checkbox-inline">' +
                '<input type="checkbox" name="EE1" value="EE1">EE1</label><br>';

            html += '</div>';
            this.__Flowdesigner.popSelWin(this._getLang('static.selnode'), html, function ($this) {
                var groupObj = $this.find('input[type="radio"]:checked');
                var groupSel = '';
                $.each(groupObj, function (i, obj) {
                    groupSel += obj.value + ';';
                })
                var checkObj = $this.find('input[type="checkbox"]:checked');
                $.each(checkObj, function (i, obj) {
                    groupSel += obj.value + ';';
                })

                alert(groupSel);
                return false;
            }, '300px');
        },

        //实例监控时点击子流程节点,显示子流程(在子类中实现)
        showSubFlow: function () {
            //调用外部接口实现监控实例的展示
            this._showMonitorData(0);
        },
        //流程跟踪图中的当前节点,发光处理
        drawNowFlight: function () {
            this.nodeShape.attr({
                style: {
                    // shadowBlur:15,
                    shadowColor: this.__Flowdesigner.options.flownode.color.now
                }
            });
            this.nodeShape.animate('style', true)
                .when(0, {
                    shadowBlur: 5
                })
                .when(900, {
                    shadowBlur: 15
                })
                .when(1800, {
                    shadowBlur: 5
                })
                .start();
        },
        //自动测试中,关闭发光
        closeFlight: function () {
            this.nodeShape.stopAnimation(true);
            this.nodeShape.attr('style', {shadowBlur: 0});
        },
        //========================================================
        //显示属性框
        _showProperties: function (pos) {
            this.__Flowdesigner.getNodeProperties().showProperties(this, pos);
        },
        //不同节点的标签可以根据需要定义
        initProPageNavForSub: function () {
            //导航条处理
            return [];
        },
        //节点类型下拉框选项(子类重写)
        initNodeTypeOption: function () {
            var nodeTypeArr = this.__Flowdesigner.options.nodetype;
            var result = [];
            $.each(this.nodeGroup || [], function (i, type) {
                result.push(nodeTypeArr[type]);
            });
            return result;
        },
        //节点类型变化时绑定的事件
        chgNodeType: function (popWin, nodePro, nodetype, data) {
            //隐藏当前大类中的所有页面
            $.each(this.nodeGroup || [], function (i, type) {
                popWin.find('.' + type).hide();
            });
            //匹配当前类型的对象显示
            this.initNodeTypeOther(popWin, nodetype);
            this.initNodeTypeSpecial(popWin, nodePro, data, nodetype);
            this.chgOperatorLst(popWin, nodePro, nodetype);
            this.initPropertiesDataSub(popWin, nodePro);
        },
        //根据节点类型对提示信息和类名称进行初始化
        initNodeTypeOther: function (popWin, nodetype) {
            var def = this.__Flowdesigner.getNodetypeDefinition(nodetype ? nodetype : this.nodetype);
            //显示跟当前节点类型相关的对象(通过class指定)
            popWin.find('.' + def.id).show();

            popWin.find('#nodetype_title').text(def.title);

            var className = popWin.find('input[name="className"]');
            var classValue = def['className']; //默认值(从下拉框中获取默认值)

            if (!nodetype) {//如果传入了nodetype说明是在更改节点类型,否则为初始化属性框
                classValue = this.data['className'];
            }
            className.val(classValue);
            if (className.val() == "") {
                popWin.find('#trClassName').hide();
            }

        },
        initPropertiesData: function (popWin, nodePro) {
            this.initNodeTypeOther(popWin);
            this.initPropertiesDataSub(popWin, nodePro);
        },
        initNodeTypeSpecial: function (popWin, nodePro, data, nodetype) {
        },
        initPropertiesDataSub: function (popWin, nodePro) {
        },
        chgOperatorLst: function (popWin, nodePro, nodetype) {
        },
        bindRuleOrClass: function (popWin, name, data, returnType) {
            this.__Flowdesigner.bindRuleOrClass(this, popWin, name, data, returnType);
        },

        //定时相关共用方法
        initTimeData: function (popWin, data) {
            var self = this;
            //selObj, items, labelName, dataName, defVal, tipOption
            this.__Flowdesigner.initSelectOptions(popWin.find('select[name="timeDate"]'),
                this._initVar_DateTime(), null, null, data['timeDate']);

            var timeRetry = popWin.find('input[name="timeRetry"]');
            timeRetry.prop("checked", data['timeRetry']);
            var timeCycle = popWin.find('input[name="timeCycle"]');
            timeCycle.val(data['timeCycle']);
            timeCycle.on('keyup', function () {
                self.__Flowdesigner.checkInputOnlyNumber($(this));
            });
            var numInput = popWin.find('input[name="num"]');
            numInput.val(data['num']);
            numInput.on('keyup', function () {
                self.__Flowdesigner.checkInputOnlyNumber($(this));
            });

            popWin.find('input[name="timeClassName"]').val(data['timeClassName']);

            self._chgTimeRetry(popWin, data['timeRetry'] != 1);
            timeRetry.on('change', function () {
                self._chgTimeRetry(popWin, !this.checked);
            });
        },
        _initVar_DateTime: function () {
            var vars = this.__drawLayer.data.flowInfo['vars'];
            var result = [];
            $.each(vars || [], function (key, item) {
                if (item && item.varType == 5) {
                    result.push({
                        label: item.varName,
                        data: item.varId
                    });
                }
            });
            return result;
        },
        _chgTimeRetry: function (popWin, checked) {
            popWin.find('input[name="timeCycle"]').attr('disabled', checked);
            popWin.find('input[name="num"]').attr('disabled', checked);
        },
        initMessage: function (popWin, data) {
            this.__Flowdesigner.initSelectOptions(popWin.find('select[name="msgPara"]'),
                this.initVar_MsgPara(), null, null, data['msgPara']);
            popWin.find('input[name="msgId"]').val(data['msgId']);
            popWin.find('input[name="msgName"]').val(data['msgName']);
            popWin.find('input[name="msgFrom"]').val(data['msgFrom']);
            popWin.find('input[name="msgTo"]').val(data['msgTo']);
            popWin.find('input[name="msgClass"]').val(data['msgClass']);
        },
        initVar_MsgPara: function () {
            var vars = this.__drawLayer.data.flowInfo['vars'];
            var result = [];
            $.each(vars || [], function (key, item) {
                if (item) {
                    result.push({
                        label: item.varName,
                        data: item.varId
                    });
                }
            });
            return result;
        },
        initSignal: function (popWin, data) {
            this.__Flowdesigner.initSelectOptions(popWin.find('select[name="signalPara"]'),
                this.initVar_MsgPara(), null, null, data['signalPara']);
            popWin.find('input[name="signalClass"]').val(data['signalClass']);
        },

        //确认属性框
        applyPropertiesData: function (popWin, nodePro) {
        },
        //处理子流程节点在map中的数据(flows为设置的所有子流程对象)
        doSubflow: function () {
            var flows = this.data['subflow']['flows'] || {};
            var obj = {};
            $.each(flows, function (i, flow) {
                if (flow) {
                    obj[flow.id] = flow.name;
                }
            });
            if (Object.keys(obj).length > 0) {
                this.map['subflow'] = obj;
            } else {
                delete this.map['subflow'];

            }
        },
        getTimeDateData: function (popWin) {
            return {
                timeClassName: popWin.find('input[name="timeClassName"]').val(),
                num: this.getIntValue(popWin.find('input[name="num"]').val(), 0),
                timeDate: popWin.find('select[name="timeDate"]').val(),
                timeRetry: popWin.find('input[name="timeRetry"]').prop('checked') ? 1 : 0,
                timeCycle: popWin.find('input[name="timeCycle"]').val()
            };
        },
        getMessageData: function (popWin) {
            return {
                msgTo: popWin.find('input[name="msgTo"]').val(),
                msgFrom: popWin.find('input[name="msgFrom"]').val(),
                msgId: popWin.find('input[name="msgId"]').val(),
                msgClass: popWin.find('input[name="msgClass"]').val(),
                msgType: '2',
                msgName: popWin.find('input[name="msgName"]').val(),
                msgPara: popWin.find('select[name="msgPara"]').val()
            };
        },
        getSignalData: function (popWin) {
            return {
                signalPara: popWin.find('select[name="signalPara"]').val(),
                signalClass: popWin.find('input[name="signalClass"]').val()
            }
        },
        //获取int值
        getIntValue: function (value, def) {
            if (value && value != '') {
                return parseInt(value);
            } else {
                return def;
            }
        },
        getStatus: function () {
            return '';
        },
        //判断一个操作在指定节点的页签上是否应该可用
        checkActionShow: function (nodeType, nodeStatus, allowNode) {
            // var allowNode = operator['node'];//允许的节点信息
            var isShow = false;
            if (allowNode.indexOf(nodeStatus) != -1) {
                if (allowNode.indexOf("~") == -1) {
                    isShow = true;
                } else {
                    //中括号中的数字表示例外节点类型,圆括号中的数字表示仅适应的节点类型
                    if (allowNode.indexOf('(') != -1) {
                        if (allowNode.indexOf(nodeType) != -1) {
                            isShow = true;
                        }
                    } else if (allowNode.indexOf('[') != -1) {
                        if (allowNode.indexOf(nodeType) == -1) {
                            isShow = true;
                        }
                    }
                }
            }
            return isShow;
        },
        //获取规则配置内容
        getRuleValue: function (popWin, name) {
            return this.__Flowdesigner.getRuleValue(popWin, name);
        }
    };

    FlowNode.extend = function (defaults) {
        var Sub = function (opts) {
            FlowNode.call(this, opts);
            defaults.init && defaults.init.call(this, opts);
        };

        zRender.util.inherits(Sub, FlowNode);

        for (var name in defaults) {
            Sub.prototype[name] = defaults[name];
        }

        return Sub;
    };
    //return true 相当于是 continue，而 return false 相当于是 break。
    return FlowNode;
});

/**
 * 开始节点
 * @author liys 201903
 */
define('flowdesigner/element/node/StartNode',['require','laydate','../FlowNode'],function (require) {
    var laydate = require('laydate');
    return require('../FlowNode').extend({

        id: 'Start',

        nodetype: '0',

        name: 'Start',
        nodeGroup: ['Node_Start', 'Node_Timer_Start', 'Node_Signal_Start', 'Node_Msg_Start'],
        eventTypeArr: [],
        exceptions: [],
        participants: [],
        operators: ['Author'],
        getStatus: function () {
            return 'start';
        },
        isStartNode: function () {
            return true;
        },
        isOnlyOneRoutNode: function () {
            return true;
        },
        isOnlyOneOutRouteNode: function () {
            return true;
        },
        addProMenuItem: function (items) {
            items.push({
                text: this._getLang('menu.nodebase'),//'基本属性'
                target: this,
                fun: '_showProperties',
                para: 0
            });

        },

        initProPageNavForSub: function (popHtml) {
            var participantsName = this._getOptions('participantsName');
            return [
                {
                    id: 'base',
                    name: this._getLang('menu.nodebase'),//'基本属性',
                    inner: [ // 装配页面到指定的id对象中
                        {
                            id: 'idSpecial',
                            html: 'start'
                        }
                    ]
                },
                {
                    id: 'operator',
                    hide: true,
                    name: this._getLang('menu.nodeoperator'),//'操作权限',
                    sub: [
                        {
                            id: 'oAuthor',
                            name: participantsName['Author'],//'主办',
                            html: 'actionform',
                            page: ['nodeAction', 'nodeForm']
                        }
                    ]
                }
            ];
        },
        initNodeTypeSpecial: function (popWin, nodePro, data, nodetype) {
            var nodeTypeArr = this.__Flowdesigner.options.nodetype;
            if (!nodetype) {
                nodetype = this.nodetype;
            }
            if (nodetype == nodeTypeArr['Node_Timer_Start'].data) {
                this._initPropertiesData_Timer(popWin, data);
            } else if (nodetype == nodeTypeArr['Node_Signal_Start'].data) {
                this._initPropertiesData_Signal(popWin, data);
            } else if (nodetype == nodeTypeArr['Node_Msg_Start'].data) {
                this._initPropertiesData_Message(popWin, data);
            }
        },
        initPropertiesDataSub: function (popWin, nodePro) {
            popWin.find('#divNxtSelType :lt(3)').hide();

            this.initNodeTypeSpecial(popWin, nodePro, this.data);

            return "";
        },

        _initPropertiesData_Timer: function (popWin, data) {
            var self = this;
            if (!data) {
                data = {
                    startMode: {
                        timeDate: '',
                        timeCycle: '0'
                    }
                };
            }
            var startMode = data.startMode;
            var timeDate = popWin.find('input[name="timeDate"]');
            timeDate.val(startMode['timeDate']);
            popWin.find('input[name="timeCycle"]').val(startMode['timeCycle']);

            laydate.render({
                elem: timeDate[0]
                , type: 'datetime'
                , done: function () {
                    self.__Flowdesigner._chgApplyBtn(popWin.find('#applyBtn'), false);
                }
            });
        },
        _initPropertiesData_Signal: function (popWin, data) {
            if (data) {
                popWin.find('input[name="signalPara"]').val(data.startMode['signalPara']);
            }

        },
        _initPropertiesData_Message: function (popWin, data) {
            if (!data) {
                return;
            }
            var startMode = data.startMode;
            popWin.find('input[name="msgId"]').val(startMode['msgId']);
            popWin.find('input[name="msgName"]').val(startMode['msgName']);
            popWin.find('input[name="msgFrom"]').val(startMode['msgFrom']);
            popWin.find('input[name="msgTo"]').val(startMode['msgTo']);
            popWin.find('input[name="msgClass"]').val(startMode['msgClass']);
            popWin.find('input[name="msgPara"]').val(startMode['msgPara']);
        },
        //===========数据回写========================
        //确认属性框
        applyPropertiesData: function (popWin, data) {
            var nodeTypeArr = this.__Flowdesigner.options.nodetype;
            var startMode = {
                type: 0
            };
            // if(this.nodetype == nodeTypeArr['Node_Timer_Start'].data){
            if (data.nodeType == 1) {
                startMode = {
                    type: 1,
                    timeDate: popWin.find('input[name="timeDate"]').val(),
                    timeCycle: popWin.find('input[name="timeCycle"]').val()
                }
            // } else if (this.nodetype == nodeTypeArr['Node_Signal_Start'].data) {
            } else if (data.nodeType == 3) {
                startMode = {
                    type: 3,
                    msgTo: popWin.find('input[name="msgTo"]').val(),
                    msgFrom: popWin.find('input[name="msgFrom"]').val(),
                    msgId: popWin.find('input[name="msgId"]').val(),
                    msgClass: popWin.find('input[name="msgClass"]').val(),
                    msgType: '2',
                    msgName: popWin.find('input[name="msgName"]').val(),
                    msgPara: popWin.find('input[name="msgPara"]').val()
                }
            // } else if (this.nodetype == nodeTypeArr['Node_Msg_Start'].data) {
            } else if (data.nodeType == 2) {
                startMode = {
                    type: 2,
                    signalPara: popWin.find('input[name="signalPara"]').val()
                };
            }

            data.startMode = startMode;
        }

    });
});

/**
 * 普通节点(基类)
 * @author liys 201903
 */
define('flowdesigner/element/node/TaskNode',['require','../FlowNode'],function(require) {

	return require('../FlowNode').extend({

		id: 'Node',

		nodetype: '10',

		name: 'Task',

		nodeGroup:['Node_Single','Node_Multi_Single','Node_Multi','Node_Order','Node_Merger','Node_Progressively'],
		exceptions:['WFE_0010','WFE_0230','WFE_0140','WFE_0060','WFE_0070','WFE_0080','WFE_0090','WFE_0120'],
		participants:['Author','SecondAuthor','Reader'],
		operators:['Author','SecondAuthor','Reader','Done','Manager','Creator'],

		getEventTypeArr:function(){
			var events = [];
			$.each(this._getOptions('eventType')||[],function(data,label){
				events.push({data:data,label:label});
			});
			return events;
		},

		getStatus:function(){
			return 'task';
		},

		addProMenuItem:function(items){
			var fd = this.__Flowdesigner;
			items.push({
				text: fd.getLang('menu.nodebase'),//基本属性
				target: this,
				fun: '_showProperties',
				para: 0
			});
			items.push({
				text: fd.getLang('menu.nodeuser'),//办理人设置
				target: this,
				fun: '_showProperties',
				para: 1
			});
			items.push({
				text: fd.getLang('menu.nodeoperator'),//操作权限
				target: this,
				fun: '_showProperties',
				para: 2
			});
			items.push({
				text: fd.getLang('menu.nodeEvent'),//事件
				target: this,
				fun: '_showProperties',
				para: 3
			});
			items.push({
				text: fd.getLang('menu.nodesubflow'),//子流程
				target: this,
				fun: '_showProperties',
				para: 4
			});
			items.push({
				text: fd.getLang('menu.nodeExtend'),//扩展规则
				target: this,
				fun: '_showProperties',
				para: 5
			});
			items.push({
				text: fd.getLang('menu.nodeException'),//异常处理
				target: this,
				fun: '_showProperties',
				para: 6
			});
			items.push({
				text: fd.getLang('menu.nodepara'),//节点参数
				target: this,
				fun: '_showProperties',
				para: 7
			});
		},
		//不同节点的标签可以根据需要定义
		initProPageNavForSub: function () {
			var participantsName = this._getOptions('participantsName');
			//导航条处理
			return  [
				{
					id:'base',
					name:this._getLang('menu.nodebase'),//'基本属性',
					inner:[ // 装配页面到指定的id对象中
						{
							id:'idSpecial',
							html:'normal'
						}
					]
				},
				{
					id: 'participant',
					name: this._getLang('menu.nodeuser'),//'办理人',
					sub:[   //用来指定二级页签
						{
							id:'pAuthor',
							name:participantsName['Author'],//'主办',
							html:'user',
							page:   //有page说明html或者id指定的页面中包含页签,且多个页签中的内容相同
							//page是用来解决页签内容共享时ID重复的问题,page指定的id会被重新赋值
							//page内容为模版中的页签id
								['userOrg','userField','userVar','userRelation',
									'userRule','userCustomer','sendMsg','control']
						},
						{
							id:'pSecondAuthor',
							name: participantsName['SecondAuthor'],//'协办',
							html:'user',
							page:['userOrg','userField','userVar','userRelation',
								'userRule','userCustomer','sendMsg','control']
						},
						{
							id:'pReader',
							name:participantsName['Reader'],//'读者',
							html:'user',
							page:['userOrg','userField','userVar','userRelation',
								'userRule','userCustomer','sendMsg','control']
						}
					]
				},
				{
					id: 'operator',
					name: this._getLang('menu.nodeoperator'),//'操作权限',
					sub:[
						{
							id:'oAuthor',
							name:participantsName['Author'],//'主办',
							html:'actionform',
							page:['nodeAction','nodeForm']
						},
						{
							id:'oSecondAuthor',
							name:participantsName['SecondAuthor'],//'协办',
							html:'actionform',
							page:['nodeAction','nodeForm']
						},
						{
							id:'oReader',
							name:participantsName['Reader'],//'读者',
							html:'actionform',
							page:['nodeAction','nodeForm']
						},
						{
							id:'oDone',
							name:participantsName['Done'],//'已办',
							html:'actionform',
							page:['nodeAction','nodeForm']
						},
						{
							id:'oManager',
							name:participantsName['Manager'],//'管理员',
							html:'actionform',
							page:['nodeAction','nodeForm']
						},
						{
							id:'oCreator',
							name:participantsName['Creator'],//'创建者',
							html:'actionform',
							page:['nodeAction','nodeForm']
						}
					]
				},
				{
					id: 'event',
					name: this._getLang('menu.nodeEvent')//'事件设置'
				},
				{
					id: 'subflow',
					name: this._getLang('menu.nodesubflow')//'子流程'
				},
				{
					id: 'extendRule',
					name: this._getLang('menu.nodeExtend')//'扩展规则'
				},
				{
					id: 'exception',
					name: this._getLang('menu.nodeException')//'异常处理'
				},
				{
					id: 'nodePara',
					name: this._getLang('menu.nodepara')//'节点参数'
				}

			];
		},
		//节点类型切换时,更新操作列表
		chgOperatorLst:function(popWin,nodePro,nodetype){
			nodePro.initActionLst(popWin,this,false,nodetype);
		},
		initNodeTypeSpecial:function(popWin,nodePro,data,nodetype){
			var nodeTypeArr = this.__Flowdesigner.options.nodetype;
			if(!nodetype){
				nodetype = this.nodetype;
			}

			if(nodetype == nodeTypeArr['Node_Multi_Single'].data) {
				this._initPropertiesData_Single(popWin,data);
			}
			else if(nodetype == nodeTypeArr['Node_Multi'].data){
				this._initPropertiesData_Multi(popWin,nodePro,data);
			}
			else if(nodetype == nodeTypeArr['Node_Merger'].data){
				this._initPropertiesData_Merger(popWin,nodePro,data);
			}
			else if(nodetype == nodeTypeArr['Node_Progressively'].data){
				this._initPropertiesData_Progressively(popWin,data);
			}
		},
		initPropertiesDataSub:function(popWin,nodePro){
			var self = this;
			popWin.find('.Node_Normal').show();
			var limitType = popWin.find('select[name="limitType"]');
			this.__Flowdesigner.initSelectOptions(limitType,
				this.__Flowdesigner.options.limitTypes, null, null, ''+this.data.limit['lType']);

			limitType.on('change',function(){
				var option = $(this).find('option[value="' + this.value + '"]');
				popWin.find('#limitShow').html(option.text());
			});
			limitType.change();

			var limitTime = popWin.find('input[name="limitTime"]');
			limitTime.val(this.data.limit['lDate']);
			limitTime.on('keyup',function () {
				self.__Flowdesigner.checkInputOnlyNumber($(this));
			});
			var limitNum = popWin.find('input[name="limitNum"]')
			limitNum.val(this.data.limit['num']);
			limitNum.on('keyup',function () {
				self.__Flowdesigner.checkInputOnlyNumber($(this));
			});
			var waringNum = popWin.find('input[name="waringNum"]');
			waringNum.val(this.data.limit['wDate']);
			waringNum.on('keyup',function () {
				self.__Flowdesigner.checkInputOnlyNumber($(this));
			});

			this.initNodeTypeSpecial(popWin,nodePro,this.data);
			this._initExtendRule(popWin);

			return "";
		},
		_initPropertiesData_Single:function(popWin,data){
			if(data){
				popWin.find('input[name="grab"]').prop("checked",data.special['grab']);
			}
			else{
				popWin.find('input[name="grab"]').prop("checked",false);
			}
		},
		_initPropertiesData_Multi:function (popWin,nodePro,data) {
			var self = this;
			if(!data || !data['special']){
				data = {
					special:{
						passType:4,
						passPara:'100',
						asyn: 0,
						lock: 0
					}
				}
			}

			var special = data.special;
			var passType = special['passType'];
			popWin.find(':radio[name="passType"][value="'+passType+'"]').prop("checked","checked");
			var passPara = popWin.find('input[name="passPara'+passType+'"]');
			//从列表中获取中文数据,并恢复
			if(passType == 2 || passType ==3){
				passPara.val(self._getCnNameFromTable(nodePro,special['passPara']));
				passPara.attr('data',special['passPara']);
			}
			else{
				passPara.val(special['passPara']);
			}

			if(passType == 1 || passType == 4){
				self.__Flowdesigner.checkAndChange(passPara,
					'checkInputOnlyNumber',3,
					function(value){
						self.__Flowdesigner._chgApplyBtn(popWin.find('#applyBtn'),false);
					});
			}

			popWin.find('input[name="asyn"]').prop("checked",special['asyn'] );
			popWin.find('input[name="lock"]').prop("checked",special['lock'] );
			self._chgPassType(popWin,nodePro,passType);
			popWin.find('input[name="asyn"]').change();

			popWin.find(':radio[name="passType"]').off('change');
			popWin.find(':radio[name="passType"]').on('change',function(){
				self._chgPassType(popWin,nodePro,this.value);
			});
			popWin.find('input[name="asyn"]').off('change');
			popWin.find('input[name="asyn"]').on('change',function(){
				var ck = $(this).prop('checked');
				if(ck){
					$('#idSpecial').find('.Node_Multi').hide();
				}
				else{
					$('#idSpecial').find('.Node_Multi').show();
				}
			});

		},
		_getCnNameFromTable:function(nodePro,passPara){
			var userObj = nodePro.tblObjArr['Author_userOrg'];
			var allUser = [];
			if(userObj){
				allUser = userObj.rows() ;
			}
			var passParaArr = [];
			if(passPara){
				passParaArr = passPara.split(';');
			}
			var showPara ='';
			$.each(passParaArr,function(i,para){
				$.each(allUser,function (i,item) {
					if(para == item.data){
						showPara += ';'+item.label;
						return false; //false = break;  true = continue;
					}
				});
			});
			return showPara==''?'':showPara.substring(1);
		},
		_chgPassType:function(popWin,nodePro,value){
			var self = this;
			$.each([1,2,3,4,5],function(i,pos){
				var tmp = popWin.find('input[name="passPara'+pos+'"]')
				tmp.attr('disabled',true);
				if(pos ==2 || pos == 3){
					tmp.off('click');
				}
			});
			var $this = popWin.find('input[name="passPara'+value+'"]');
			$this.attr('disabled',false);
			if(value == 2 || value==3){
				$this.on('click',function () {
					var html = '<select name="popSel" multiple style="width:100%;height:200px">';
					var userObj = nodePro.tblObjArr['Author_userOrg'];
					var allUser = [];
					if(userObj){
						allUser = userObj.rows() ;
					}
					var defVal = $this.attr('data');
					if(!defVal){
						defVal =';';
					}
					else{
						defVal = ';'+defVal +';';
					}
					var cnOrg = self.__Flowdesigner.orgCnNames;
					$.each(allUser || [],function(i,item){
						if(!(item && item.type == 'person')){
							return true;
						}
						var sel = '';
						if(defVal.indexOf(';'+item.data+';') !=-1){
							sel = 'selected';
						}
						var label = item.label;
						if(item.data == label){
							var orgs = item['data'].split('/');
							var suf = ''
							if(orgs.length >1){
								var tmp = orgs[1].split('_');
								suf = ('/'+cnOrg[tmp[1]]);
							}
							label = cnOrg[orgs[0]] + suf;
						}

						html += '<option value="'+item.data+'"' + sel +'>'+label +'</option>';
					});
					html += '</select>';
					self.__Flowdesigner.popSelWin(self._getLang('static.seluser'),html,function($popContent){
						var selObj = $popContent.find('select[name="popSel"]');
						var label='',ids='';
						$.each(selObj.val() || [],function(i,id){
							var option = selObj.find('option[value="'+id+'"]');
							label += ';'+option.text();
							ids += ';'+id;
						});

						if(ids ==''){
							self._showMsg(self._getLang('static.seluser'));//'请选择办理人'
							return false;
						}
						$this.val(label.substring(1));
						$this.attr('data',ids.substring(1));
						self.__Flowdesigner._chgApplyBtn(popWin.find('#applyBtn'),false);
					});
				});
			}
			else if(value ==1 || value==4){
				self.__Flowdesigner.checkAndChange($this,
					'checkInputOnlyNumber',3,
					function(value){
						self.__Flowdesigner._chgApplyBtn(popWin.find('#applyBtn'),false);
					});
			}

		},
		_initPropertiesData_Merger: function (popWin,nodePro,data) {
			var self = this;
			if(!data || !data['special'] || !data['special']['merger']){
				data = {
					special:{
						merger:{
							mergerAll: 0,    //合并所有能到达的分支
							submitAgain: 0,  //离开后,其他分支到达允许重新激活
							reSelect: 0,     //重新激活时,允许重新选择办理人
							cancelOther: 0,  //激活后,其他未到达的分支取消
							leaveCancel:0,	//离开后,取消其他未到达的分支
							activeType: 4,	 //激活方式:1.分支超过X个,2.指定分支中任意一个到达,3,指定分支全部到达,
										     //       4.所有分支到达后激活,5.立即激活,6.扩展规则
							activePara: '',  //对应参数
							leaveType: 4,    //离开方式:1.分支已到X个,2.指定分支中任意一个到达,3.指定分支全部到达,
										     //       4.所有分支到达,5.自行确定,6.扩展规则
							leavePara: ''    //对应参数
						}
					}
				}
			}
			var merger = data.special['merger'];
			var mergerAll = popWin.find('input[name="mergerAll"]');
			var submitAgain = popWin.find('input[name="submitAgain"]');
			var reSelect = popWin.find('input[name="reSelect"]');
			var cancelOther = popWin.find('input[name="cancelOther"]');
			var leaveCancel = popWin.find('input[name="leaveCancel"]');

			mergerAll.prop("checked", merger['mergerAll'] ==1);
			submitAgain.prop("checked", merger['submitAgain'] ==1);
			reSelect.prop("checked", merger['reSelect'] ==1);
			cancelOther.prop("checked", merger['cancelOther'] ==1);
			leaveCancel.prop("checked",merger['leaveCancel'] ==1);

			if(merger['submitAgain'] ==1){
				reSelect.attr('disabled', false);
			}
			else{
				reSelect.attr('disabled', true);
				reSelect.prop("checked", false);
			}
			/*20200508 LIYS 取消约束
			//单选框的约束处理
			mergerAll.on('change', function () {
				if (this.checked) {
					reSelect.attr('disabled', false);

					//submitAgain.attr('disabled', true);
					//submitAgain.prop("checked", false);
				} else {
					reSelect.attr('disabled', true);
					reSelect.prop("checked", false);

					//submitAgain.attr('disabled', false);
				}
			});
			//*/
			submitAgain.on('change', function () {
				if (this.checked) {
					reSelect.attr('disabled', false);
				} else {
					reSelect.attr('disabled', true);
					reSelect.prop("checked", false);
				}
			});
			cancelOther.on('change', function () {
				//立即激活和等待所有分支激活,与此互斥
				if(!cancelOther.prop('checked')){
					return;
				}
				//先取消选中
				cancelOther.prop('checked',false);
				var activeType = popWin.find(':radio[name="activeType"]:checked').val();
				var leaveType =  popWin.find(':radio[name="leaveType"]:checked').val();
				if (activeType == '4' || activeType == '5') {
					//"激活规则为【立即激活】或者【所有分支到达后激活】时，不允许勾选此选项。"
					self.__Flowdesigner.showMsg(self._getLang('static.mergerMsg1'));
					return;
				}
				if (leaveType == '4' && activeType != '4') {
					//离开规则选择【等到所有分支】时，不允许勾选此选项。
					self.__Flowdesigner.showMsg(self._getLang('static.mergerMsg2'));
					return;
				}
				if (activeType == '1' && leaveType == '1') {
					if (parseInt(popWin.find('input[name="activePara1"]').val())
						< parseInt(popWin.find('input[name="leavePara1"]').val())) {
						//激活分支数小于离开规则分支数时，不允许勾选此选项。
						self.__Flowdesigner.showMsg(self._getLang('static.mergerMsg3'));
						return;
					}
				}
				//如果判断通过,则让期选中
				cancelOther.prop('checked',true);
				/* 20200508 LIYS 取消约束
				if (!mergerAll.prop('checked')) {
					//2.在不合并所有分支时mergerAll == false
					//  离开后,其他分支到达后重新激活节点 与此也互斥
					submitAgain.prop("checked", false);
					reSelect.prop("checked", false);
				}
				//*/
			});

			popWin.find(':radio[name="activeType"][value="'+merger['activeType']+'"]').prop("checked","checked");
			popWin.find(':radio[name="leaveType"][value="'+merger['leaveType']+'"]').prop("checked","checked");
			var activePara = popWin.find('input[name="activePara'+merger['activeType']+'"]');
			var leavePara = popWin.find('input[name="leavePara'+merger['leaveType']+'"]');
			var allnodes = this.__drawLayer._nodes;
			if(activePara){
				if(merger['activeType'] == 2 || merger['activeType'] == 3){
					if(merger['activePara']){
						var label = '';
						$.each(merger['activePara'].split(';') || [],function(i,nodeid){
							label += allnodes[nodeid].name +'('+nodeid+');';
						});
						activePara.val(label);
						activePara.attr('data',merger['activePara']);
					}
					else{
						activePara.val('');
						activePara.attr('data','');
					}
				}
				else{
					activePara.val(merger['activePara']);
				}
			}
			if(leavePara){
				if(merger['activeType'] == 2 || merger['activeType'] == 3) {
					if(merger['leavePara']){
						var label = '';
						$.each(merger['leavePara'].split(';') || [], function (i, nodeid) {
							label += allnodes[nodeid].name +'('+nodeid+');';
						});
						leavePara.val(label);
						leavePara.attr('data', merger['leavePara']);
					}
					else{
						leavePara.val('');
						leavePara.attr('data','');
					}
				}
				else{
					leavePara.val(merger['leavePara']);
				}
			}
			self.__Flowdesigner.checkAndChange(popWin.find('input[name="activePara1"]'),
				'checkInputOnlyNumber',2,
				function(value){
					self.__Flowdesigner._chgApplyBtn(popWin.find('#applyBtn'),false);
				});
			self.__Flowdesigner.checkAndChange(popWin.find('input[name="leavePara1"]'),
				'checkInputOnlyNumber',2,
				function(value){
					self.__Flowdesigner._chgApplyBtn(popWin.find('#applyBtn'),false);
				});

			self._chgMergerType(popWin,'activePara',merger['activeType'],nodePro);
			self._chgMergerType(popWin,'leavePara',merger['leaveType'],nodePro);
			popWin.find(':radio[name="activeType"]').on('change',function(){
				self._chgMergerType(popWin,'activePara',this.value,nodePro);
			});
			popWin.find(':radio[name="leaveType"]').on('change',function(){
				self._chgMergerType(popWin,'leavePara',this.value,nodePro);
			});
		},
		_chgMergerType:function(popWin,name,value,nodePro){
			var self = this;
			$.each([1,2,3,6],function(i,pos){
				var tmp = popWin.find('input[name="'+name+pos+'"]')
				tmp.attr('disabled',true);
				if(pos ==2 || pos == 3){
					tmp.off('click');
				}
			});
			var $this = popWin.find('input[name="'+name+value+'"]');
			$this.attr('disabled',false);
			if(value == 2 || value==3){
				$this.on('click',function () {
					nodePro.selectNodeMulti(self,
						function(selnode){
							var label='',data='';
							$.each(selnode.val() || [],function(i,nodeid){
								if(nodeid) {
									var option = selnode.find('option[value="' + nodeid + '"]');
									data += ';' + nodeid;
									label += ';' + option.text();
								}
							});
							if(data !=''){
								data = data.substring(1);
								label = label.substring(1);
							}
							$this.val(label);
							$this.attr('data',data);
							self.__Flowdesigner._chgApplyBtn(popWin.find('#applyBtn'),false);
						},
						function(item){
							//判断是否有路由指向当前节点
							var back = false;
							//判断item节点的路由是否指向node
							$.each(item.routes || [], function (i, route) {
								if (route.toNode.id == self.id) {
									back = true;
									return false;
								}
							});
							return back;
						},
						$this.attr('data')+';'
					);
				});
			}
		},
		_initPropertiesData_Progressively:function(popWin,data){
			if(data && data['special']){
				popWin.find('input[name="progressivelyClassName"]')
					.val(data.special.progressivelyClassName);
			}
		},

		//扩展规则初始化
		_initExtendRule:function(popWin){
			var self = this;

			//进入
			this.bindRuleOrClass(popWin,'entry',this.data.entry);

			//离开
			this.bindRuleOrClass(popWin,'leave',this.data.leave);

			//激活
			var startMode = this.data.startMode;
			var startModeType = popWin.find('select[name="startModeType"]');
			startModeType.val(startMode['type']);

			this._chgStartModeType(popWin,startMode['type'],startMode);
			startModeType.on('change',function(){
				self._chgStartModeType(popWin,this.value,startModeType);
			});

			//startModeType.change();
		},
		_chgStartModeType:function(popWin,value,data){
			$.each([1,2,3],function(i,pos){
				popWin.find('.startModeType'+pos).hide();
			});
			if(value > 0){
				popWin.find('.startModeType'+value).show();
				if(value ==1){
					this._initTimeDate(popWin,data);
				}
				else if(value == 2){
					this._initMessage(popWin,data);
				}
				else if(value == 3){
					this._initSignal(popWin,data);
				}
			}
		},
		_initTimeDate:function(popWin,data){
			if(!data){
				data = {	//定时激活时的默认值
					type:1,
					timeClassName:"",
					num:0,
					timeDate:"",
					timeRetry:1,
					timeCycle:1000
				}	;
			}

			this.initTimeData(popWin,data);
		},
		_initMessage:function(popWin,data){
			if(!data){
				data = {	//定时激活时的默认值
					type:2,
					msgTo: '',
					msgFrom: '',
					msgId: '',
					msgClass: '',
					msgType: '2',
					msgName: '',
					msgPara: ''
				};
			}

			this.initMessage(popWin,data);
		},
		_initSignal:function(popWin,data){
			if(!data){
				data = {	//定时激活时的默认值
					type:3,
					signalPara:'',
					signalClass:''
				}	;
			}

			this.initSignal(popWin,data);
		},

		//===========数据回写========================
		//确认属性框
		applyPropertiesData:function(popWin,data){
			var result = this._applyBaseData(popWin,data);
			if(result !=''){
				return result;
			}
			this._applyExtendRule(popWin,data);
			return '';
		},
		_applyBaseData:function(popWin,data){
			data.limit = {};
			data.limit['lDate'] = this.getIntValue(popWin.find('input[name="limitTime"]').val(),0);
			data.limit['lType'] = this.getIntValue(popWin.find('select[name="limitType"]').val(),1);
			data.limit['num'] 	 = this.getIntValue(popWin.find('input[name="limitNum"]').val(),0);
			data.limit['wDate'] = this.getIntValue(popWin.find('input[name="waringNum"]').val(),0);

			var nodeTypeArr = this.__Flowdesigner.options.nodetype;
			data['special'] = {};
			var nodetype = data.nodeType;
			if(nodetype == nodeTypeArr['Node_Multi_Single'].data) {
				data.special['grab'] = popWin.find('input[name="grab"]').prop("checked") ?1:0;
			}
			else if(nodetype == nodeTypeArr['Node_Multi'].data){
				var passType = this.getIntValue(popWin.find(':radio[name="passType"]:checked').val(),4);
				data.special['passType'] = passType;

				if(passType == 2 || passType == 3){
					data.special['passPara'] = popWin.find('input[name="passPara'+passType+'"]').attr('data');
				}
				else{
					data.special['passPara'] = popWin.find('input[name="passPara'+passType+'"]').val();
				}
				data.special['asyn'] = popWin.find('input[name="asyn"]').prop("checked")?1:0;
				data.special['lock'] = popWin.find('input[name="lock"]').prop("checked")?1:0;
			}
			else if(nodetype == nodeTypeArr['Node_Merger'].data){
				var merger = {};
				merger['mergerAll'] = popWin.find('input[name="mergerAll"]').prop("checked")?1:0;
				merger['submitAgain'] = popWin.find('input[name="submitAgain"]').prop("checked")?1:0;
				merger['reSelect'] = popWin.find('input[name="reSelect"]').prop("checked")?1:0;
				merger['cancelOther'] = popWin.find('input[name="cancelOther"]').prop("checked")?1:0;
				merger['leaveCancel'] = popWin.find('input[name="leaveCancel"]').prop("checked")?1:0;

				var aT = this.getIntValue(popWin.find(':radio[name="activeType"]:checked').val(),4);
				var lT = this.getIntValue(popWin.find(':radio[name="leaveType"]:checked').val(),4);
				merger['activeType'] = aT;
				merger['leaveType'] = lT;
				if(aT ==2 || aT == 3){
					var aPara = popWin.find('input[name="activePara'+aT+'"]').attr('data');
					if(aPara == undefined || aPara ==''){
						//合并激活规则中的选项需要指定节点
						return this._getLang('static.mergerMsg4');
					}
					merger['activePara'] = aPara;
				}
				else{
					merger['activePara'] = popWin.find('input[name="activePara'+aT+'"]').val();
				}
				if(lT== 2 || lT == 3){
					var lPara = popWin.find('input[name="leavePara'+lT+'"]').attr('data');
					if(lPara == undefined || lPara == ''){
						//'合并离开规则中的选项需要指定节点'
						return this._getLang('static.mergerMsg5');
					}
					merger['leavePara'] =lPara;
				}
				else{
					merger['leavePara'] = popWin.find('input[name="leavePara'+lT+'"]').val();
				}

				data.special['merger'] = merger;
			}
			else if(nodetype == nodeTypeArr['Node_Progressively'].data){
				data.special.progressivelyClassName =
					popWin.find('input[name="progressivelyClassName"]').val();
			}
			return '';
		},
		_applyExtendRule:function(popWin,data){
			data.entry = this.getRuleValue(popWin,'entry');
			data.leave = this.getRuleValue(popWin,'leave');

			var startMode = {};
			var sType = this.getIntValue(popWin.find('select[name="startModeType"]').val(),0);

			if(sType == 1){
				startMode = this.getTimeDateData(popWin);
			}
			else if(sType == 2){
				startMode = this.getMessageData(popWin);
			}
			else if(sType == 3){
				startMode = this.getSignalData(popWin);
			}
			//这个一定要放在下面
			startMode['type'] = sType;
			data.startMode = startMode;
		}
	});
});
/**
 * 结束节点
 * @author liys 201903
 */
define('flowdesigner/element/node/EndNode',['require','../FlowNode'],function(require) {
	return require('../FlowNode').extend({

		id: 'End',

		nodetype: '100',

		name: 'End',
		nodeGroup:['Node_End','Node_End_Instance'],

		exceptions:['WFE_0060','WFE_0160'],
		participants:['Reader'],
		operators:['Reader','Done','Manager','Creator'],
		getEventTypeArr:function(){
			return [
				{data:'flowin',label:this._getOptions('eventType')['flowin']}
			];
		},
		getStatus:function(){
			return 'end';
		},
        isEndNode:function(){
            return true;
        },
		autoTest:function(){
			if (this.data) {
				this.__Flowdesigner.showMsg(this._getLang('menu.testend'));
			}
		},
		addProMenuItem:function(items){
			var fd = this.__Flowdesigner;
			items.push({
				text: fd.getLang('menu.nodebase'),//基本属性
				target: this,
				fun: '_showProperties',
				para: 0
			});
			items.push({
				text: fd.getLang('menu.nodeuser'),//办理人设置
				target: this,
				fun: '_showProperties',
				para: 1
			});
			items.push({
				text: fd.getLang('menu.nodeoperator'),//操作权限
				target: this,
				fun: '_showProperties',
				para: 2
			});
			items.push({
				text: fd.getLang('menu.nodeEvent'),//事件
				target: this,
				fun: '_showProperties',
				para: 3
			});
			items.push({
				text: fd.getLang('menu.nodeException'),//异常处理
				target: this,
				fun: '_showProperties',
				para: 4
			});
			items.push({
				text:  fd.getLang('menu.nodepara'),//节点参数
				target: this,
				fun: '_showProperties',
				para: 5
			});
		},
		initProPageNavForSub: function (popHtml) {
			var participantsName = this._getOptions('participantsName');
			return  [
				{
					id:'base',
					name:this._getLang('menu.nodebase'),//'基本属性'
					inner:[
						{
							id:'idSpecial',
							html:'end'
						}
					]
				},
				{
					id: 'participant',
					name: this._getLang('menu.nodeuser'),//'办理人',
					sub:[
						{
							id:'pReader',
							name:participantsName['Reader'],//'读者',
							html:'user',
							page:['userOrg','userField','userVar','userRelation',
								'userRule','userCustomer','sendMsg','control']
						}
					]
				},
				{
					id: 'operator',
					name: this._getLang('menu.nodeoperator'),//'操作权限',
					sub:[

						{
							id:'oReader',
							name:participantsName['Reader'],//'读者',
							html:'actionform',
							page:['nodeAction','nodeForm']
						},
						{
							id:'oDone',
							name:participantsName['Done'],//'已办',
							html:'actionform',
							page:['nodeAction','nodeForm']
						},
						{
							id:'oManager',
							name:participantsName['Manager'],//'管理员',
							html:'actionform',
							page:['nodeAction','nodeForm']
						},
						{
							id:'oCreator',
							name:participantsName['Creator'],//'创建者',
							html:'actionform',
							page:['nodeAction','nodeForm']
						}
					]
				},
				{
					id: 'event',
					name: this._getLang('menu.nodeEvent')//'事件设置'
				},
				{
					id: 'exception',
					name: this._getLang('menu.nodeException')//'异常处理'
				},
				{
					id: 'nodePara',
					name: this._getLang('menu.nodepara')//'节点参数'
				}

			];
		},

		initPropertiesDataSub:function(popWin,nodePro){
			popWin.find('#divNxtSelType').hide();
			this.bindRuleOrClass(popWin,'entry',this.data.entry);
			return "";
		},
		//确认属性框
		applyPropertiesData:function(popWin,data){

			data.entry = this.getRuleValue(popWin,'entry');
		}


	});
});


/**
 * 事件节点
 * @author liys 201903
 */
define('flowdesigner/element/node/EventNode',['require','../FlowNode'],function(require) {

	return require('../FlowNode').extend({

		id: 'Event',

		nodetype: '81',

		name: 'Event',
		nodeGroup:['Node_Event_Intermediate','Node_Event_Timer','Node_Event_Message',
			'Node_Event_Signal_Throw','Node_Event_Signal_Catch'],
		exceptions:['WFE_0230','WFE_0020','WFE_0030'],
		participants:['Reader'],
		operators:['Reader','Done','Manager','Creator'],
		eventTypeArr:[],

		getStatus:function(){
			return 'event';
		},
        isOnlyOneOutRouteNode: function () {
            return true;
        },
		addProMenuItem:function(items){
			items.push({
				text: this._getLang('menu.nodebase'),//基本属性
				target: this,
				fun: '_showProperties',
				para: 0
			});
			items.push({
				text: this._getLang('menu.nodeuser'),//办理人设置
				target: this,
				fun: '_showProperties',
				para: 1
			});
			items.push({
				text: this._getLang('menu.nodeoperator'),//操作权限
				target: this,
				fun: '_showProperties',
				para: 2
			});

			items.push({
				text: this._getLang('menu.nodeExtend'),//扩展规则
				target: this,
				fun: '_showProperties',
				para: 3
			});
			items.push({
				text:  this._getLang('menu.nodeException'),//异常处理
				target: this,
				fun: '_showProperties',
				para: 4
			});
			items.push({
				text: this._getLang('menu.nodepara'),//节点参数
				target: this,
				fun: '_showProperties',
				para: 5
			});
		},
		initProPageNavForSub: function (popHtml) {
			var participantsName = this._getOptions('participantsName');
			return  [
				{
					id:'base',
					name:this._getLang('menu.nodebase'),//'基本属性',
					inner:[ // 装配页面到指定的id对象中
						{
							id:'idSpecial',
							html:'event'
						}
					]
				},
				{
					id: 'participant',
					name: this._getLang('menu.nodeuser'),//'办理人',
					sub:[
						{
							id:'pReader',
							name:participantsName['Reader'],//'读者',
							html:'user',
							page:['userOrg','userField','userVar','userRelation',
								'userRule','userCustomer','sendMsg','control']
						}
					]
				},
				{
					id: 'operator',
					name: this._getLang('menu.nodeoperator'),//'操作权限',
					sub:[
						{
							id:'oReader',
							name:participantsName['Reader'],//'读者',
							html:'actionform',
							page:['nodeAction','nodeForm']
						},
						{
							id:'oDone',
							name:participantsName['Done'],//'已办',
							html:'actionform',
							page:['nodeAction','nodeForm']
						},
						{
							id:'oManager',
							name:participantsName['Manager'],//'管理员',
							html:'actionform',
							page:['nodeAction','nodeForm']
						},
						{
							id:'oCreator',
							name:participantsName['Creator'],//'创建者',
							html:'actionform',
							page:['nodeAction','nodeForm']
						}
					]
				},
				{
					id: 'extendRule',
					name: this._getLang('menu.nodeExtend')//'扩展规则'
				},
				{
					id: 'exception',
					name: this._getLang('menu.nodeException')//'异常处理'
				},
				{
					id: 'nodePara',
					name: this._getLang('menu.nodepara')//'节点参数'
				}

			];
		},
		initNodeTypeSpecial:function(popWin,nodePro,data,nodetype){
			var nodeTypeArr = this.__Flowdesigner.options.nodetype;
			if(!nodetype){
				nodetype = this.nodetype;
			}
			if(nodetype == nodeTypeArr['Node_Event_Intermediate'].data){
				this._initPropertiesData_Intermediate(popWin,data);
			}
			else if(nodetype == nodeTypeArr['Node_Event_Timer'].data){
				this._initPropertiesData_Timer(popWin,data);
			}
			else if(nodetype == nodeTypeArr['Node_Event_Message'].data){
				this._initPropertiesData_Message(popWin,data);
			}
			else {
				this._initPropertiesData_Signal(popWin,data);
			}
		},
		initPropertiesDataSub:function(popWin,nodePro){
			this.initNodeTypeSpecial(popWin,nodePro,this.data);

			this._initExtendRule(popWin);
			return "";
		},
		_initPropertiesData_Intermediate:function(popWin,data){
			if(data){
				popWin.find('input[name="eventClassName"]').val(data.special['eventClassName']);
			}
		},
		_initPropertiesData_Timer:function(popWin,data) {
			var self = this;
			if (!data) {
				data = {
					special: {
						timeClassName: '',
						num: 0,
						timeDate: '',
						timeRetry: 1,
						timeCycle: ''
					}
				};
			}
			this.initTimeData(popWin,data.special);
		},
		_initPropertiesData_Message:function(popWin,data){
			var self = this;
			if(!data){
				data = {
					special:{
						msgTo: '',
						msgFrom: '',
						msgId: '',
						msgClass: '',
						msgType: '2',
						msgName: '',
						msgPara: ''
					}
				}	;
			}
			var special = data.special;
			this.initMessage(popWin,special);
		},

		_initPropertiesData_Signal:function(popWin,data){
			var self = this;
			if(!data){
				data = {
					special:{
						signalPara:'',
						signalClass:''
					}
				};
			}
			var special = data.special;
			//selObj, items, labelName, dataName, defVal, tipOption
			this.initSignal(popWin,special);
		},


		//扩展规则初始化
		_initExtendRule:function(popWin) {
			//进入
			this.bindRuleOrClass(popWin, 'entry', this.data.entry);

			popWin.find('.Node_Normal').html('');
		},

		//===========数据回写========================
		//确认属性框
		applyPropertiesData:function(popWin,data){
			var nodeTypeArr = this.__Flowdesigner.options.nodetype;
			data.special = {};
			if(this.nodetype == nodeTypeArr['Node_Event_Intermediate'].data){
				data.special['eventClassName'] = popWin.find('input[name="eventClassName"]').val();
			}
			else if(this.nodetype == nodeTypeArr['Node_Event_Timer'].data){
				data.special = this.getTimeDateData(popWin);
			}
			else if(this.nodetype == nodeTypeArr['Node_Event_Message'].data){
				data.special = this.getMessageData(popWin);
			}
			else {
				data.special = this.getSignalData(popWin);
			}

			data.entry = this.getRuleValue(popWin,'entry');
		}
	});
});
/**
 * 网关节点
 * @author liys 201903
 */
define('flowdesigner/element/node/GatewayNode',['require','../FlowNode'],function(require) {

	return require('../FlowNode').extend({

		id: 'Gateway',

		nodetype: '72',

		name: 'Gateway',
		nodeGroup:['Node_GateWay_Merge','Node_GateWay_Split'],
		exceptions:['WFE_0230','WFE_0040'],
		operators:['Reader','Done','Manager','Creator'],
		eventTypeArr:[],
		participants:[],
		getStatus:function(){
			return 'gateway';
		},
		addProMenuItem:function(items){
			items.push({
				text: this._getLang('menu.nodebase'),//'基本属性'
				target: this,
				fun: '_showProperties',
				para: 0
			});

			items.push({
				text:  this._getLang('menu.nodeoperator'),//'操作权限'
				target: this,
				fun: '_showProperties',
				para: 1
			});

			items.push({
				text:  this._getLang('menu.nodeException'),//'异常处理'
				target: this,
				fun: '_showProperties',
				para: 2
			});
			items.push({
				text:  this._getLang('menu.nodepara'),//'节点参数'
				target: this,
				fun: '_showProperties',
				para: 3
			});
		},
		initProPageNavForSub: function (popHtml) {
			var participantsName = this._getOptions('participantsName');
			return  [
				{
					id:'base',
					name: this._getLang('menu.nodebase'),//'基本属性',
					inner:[ // 装配页面到指定的id对象中
						{
							id:'idSpecial',
							html:'gateway'
						}
					]
				},
				{
					id: 'operator',
					name:  this._getLang('menu.nodeoperator'),//'操作权限',
					sub:[
						{
							id:'oReader',
							name:participantsName['Reader'],//'读者',
							html:'actionform',
							page:['nodeAction','nodeForm']
						},
						{
							id:'oDone',
							name:participantsName['Done'],//'已办',
							html:'actionform',
							page:['nodeAction','nodeForm']
						},
						{
							id:'oManager',
							name:participantsName['Manager'],//'管理员',
							html:'actionform',
							page:['nodeAction','nodeForm']
						},
						{
							id:'oCreator',
							name:participantsName['Creator'],//'创建者',
							html:'actionform',
							page:['nodeAction','nodeForm']
						}
					]
				},

				{
					id: 'exception',
					name:  this._getLang('menu.nodeException')//'异常处理'
				},
				{
					id: 'nodePara',
					name:  this._getLang('menu.nodepara')//'节点参数'
				}

			];
		},
		initNodeTypeSpecial:function(popWin,nodePro,data,nodetype){
			var nodeTypeArr = this.__Flowdesigner.options.nodetype;
			if(!nodetype){
				nodetype = this.nodetype;
			}
			if(nodetype == nodeTypeArr['Node_GateWay_Merge'].data){
				this._initPropertiesData_Merge(popWin,data);
			}
			else if(nodetype == nodeTypeArr['Node_GateWay_Split'].data){
				this._initPropertiesData_Split(popWin,data);
			}
		},
		initPropertiesDataSub:function(popWin,nodePro){
			if(popWin.find('select[name="nodeType"]').val() == this.__Flowdesigner.options.nodetype['Node_GateWay_Split'].data){
				popWin.find('#divNxtSelType :first').show();
			}
			else{
				popWin.find('#divNxtSelType :first').hide();
			}
			if(popWin.find('select[name="nodeType"]').val() != this.nodetype){
				popWin.find(':radio[name="nxtSelType"][value="2"]').prop("checked", true);
			}
			this.initNodeTypeSpecial(popWin,nodePro,this.data);
			return "";
		},

		_initPropertiesData_Merge:function (popWin,data) {
			var self = this;
			if(!data){
				data = {
					special:{
						gateway:{
							className:'',   //实现类与规则互斥
							id:'',          //规则数据id
							script:'',      //可执行的规则脚本内容
							text:''         //用于显示的规则内容
						},
						merger:{
							cancelOther:0,
							submitAgain:0
						}
					}
				};
			}
			var merger = data.special['merger'] ||{};
			var cancelOther = popWin.find('input[name="cancelOther"]');
			var submitAgain = popWin.find('input[name="submitAgain"]');
			cancelOther.prop("checked", merger['cancelOther'] || false);
			submitAgain.prop("checked", merger['submitAgain'] || false);

			cancelOther.on('change',function(){
				if(this.checked){
					submitAgain.prop("checked",false);
				}
			});
			submitAgain.on('change',function(){
				if(this.checked){
					cancelOther.prop("checked",false);
				}
			});

			self.bindRuleOrClass(popWin,'merger',data.special['gateway']||{});

		},
		_initPropertiesData_Split:function (popWin,data) {
			if(data){
				popWin.find('input[name="splitClassName"]')
					.val(data.special['gateway']['className']);
			}
		},

		//===========数据回写========================
		//确认属性框
		applyPropertiesData:function(popWin,data){
			var nodeTypeArr = this.__Flowdesigner.options.nodetype;
			data['special']={};
			if(this.nodetype == nodeTypeArr['Node_GateWay_Merge'].data){
				data.special.merger = {
					cancelOther:popWin.find('input[name="cancelOther"]').prop('checked')?1:0,
					submitAgain:popWin.find('input[name="submitAgain"]').prop('checked')?1:0
				};
				data.special.gateway = this.getRuleValue(popWin,'merger');
			}
			else if(this.nodetype == nodeTypeArr['Node_GateWay_Split'].data){
				data.special['gateway']={
					className:popWin.find('input[name="splitClassName"]').val()
				};
			}
		}
	});
});

/**
 * 自动节点
 * @author liys 201903
 */
define('flowdesigner/element/node/RobotNode',['require','../FlowNode'],function(require) {

	return require('../FlowNode').extend({

		id: 'Robot',

		type: '41',

		name: 'Robot',
		nodeGroup:['Node_Auto_Program'],
		exceptions:['WFE_0230','WFE_0120','WFE_0200'],
		participants:['Reader'],
		operators:['Reader','Done','Manager','Creator'],
		eventTypeArr:[],
		getStatus:function(){
			return 'robot';
		},
        isOnlyOneOutRouteNode: function () {
            return true;
        },
		addProMenuItem:function(items){
			items.push({
				text: this._getLang('menu.nodebase'),//'基本属性'
				target: this,
				fun: '_showProperties',
				para: 0
			});
			items.push({
				text:  this._getLang('menu.nodeuser'),//'办理人设置'
				target: this,
				fun: '_showProperties',
				para: 1
			});
			items.push({
				text:  this._getLang('menu.nodeoperator'),//'操作权限'
				target: this,
				fun: '_showProperties',
				para: 2
			});

			items.push({
				text:  this._getLang('menu.nodeExtend'),//'扩展规则'
				target: this,
				fun: '_showProperties',
				para: 3
			});
			items.push({
				text:  this._getLang('menu.nodeException'),//'异常处理'
				target: this,
				fun: '_showProperties',
				para: 4
			});
			items.push({
				text:  this._getLang('menu.nodepara'),//'节点参数'
				target: this,
				fun: '_showProperties',
				para: 5
			});
		},

		initProPageNavForSub: function (popHtml) {
			var participantsName = this._getOptions('participantsName');
			return  [
				{
					id:'base',
					name: this._getLang('menu.nodebase'),//'基本属性',
					inner:[ // 装配页面到指定的id对象中
						{
							id:'idSpecial',
							html:'robot'
						}
					]
				},
				{
					id: 'participant',
					name:  this._getLang('menu.nodeuser'),//'办理人',
					sub:[
						{
							id:'pReader',
							name:participantsName['Reader'],//'读者',
							html:'user',
							page:['userOrg','userField','userVar','userRelation',
								'userRule','userCustomer','sendMsg','control']
						}
					]
				},
				{
					id: 'operator',
					name:  this._getLang('menu.nodeoperator'),//'操作权限',
					sub:[
						{
							id:'oReader',
							name:participantsName['Reader'],//'读者',
							html:'actionform',
							page:['nodeAction','nodeForm']
						},
						{
							id:'oDone',
							name:participantsName['Done'],//'已办',
							html:'actionform',
							page:['nodeAction','nodeForm']
						},
						{
							id:'oManager',
							name:participantsName['Manager'],//'管理员',
							html:'actionform',
							page:['nodeAction','nodeForm']
						},
						{
							id:'oCreator',
							name:participantsName['Creator'],//'创建者',
							html:'actionform',
							page:['nodeAction','nodeForm']
						}
					]
				},
				{
					id: 'extendRule',
					name:  this._getLang('menu.nodeExtend')//'扩展规则'
				},
				{
					id: 'exception',
					name: this._getLang('menu.nodeException')//'异常处理'
				},
				{
					id: 'nodePara',
					name: this._getLang('menu.nodepara')//'节点参数'
				}

			];
		},

		initPropertiesDataSub:function(popWin,nodePro){
			popWin.find('input[name="robotClassName"]')
				.val(this.data.special['robotClassName']);

			this._initExtendRule(popWin);
		},
		//扩展规则初始化
		_initExtendRule:function(popWin) {
			//进入
			this.bindRuleOrClass(popWin, 'entry', this.data.entry);

			popWin.find('.Node_Normal').html('');
		},
		//===========数据回写========================
		//确认属性框
		applyPropertiesData:function(popWin,data){
			data.entry = this.getRuleValue(popWin,'entry');
			data.special = {};
			data.special['robotClassName'] = popWin.find('input[name="robotClassName"]').val();
		}

	});
});
/**
 * 引擎交互节点
 * @author liys 201903
 */
define('flowdesigner/element/node/ClusterNode',['require','../FlowNode'],function(require) {
	return require('../FlowNode').extend({

		id: 'Cluster',

		nodetype: '210',

		name: 'Cluster',
		nodeGroup:['Node_Mutual'],
		operators:['Reader','Done','Manager','Creator'],
		eventTypeArr:[],
		exceptions:[],
		participants:[],

		getStatus:function(){
			return 'cluster';
		},
        isOnlyOneOutRouteNode: function () {
            return true;
        },
		addProMenuItem:function(items){
			items.push({
				text: this._getLang('menu.nodebase'),//节点属性
				target: this,
				fun: '_showProperties',
				para: 0
			});
			items.push({
				text: this._getLang('menu.nodeoperator'),//'操作权限'
				target: this,
				fun: '_showProperties',
				para: 1
			});
			items.push({
				text: this._getLang('menu.nodecluster'),//交互设置
				target: this,
				fun: '_showProperties',
				para: 2
			});
		},

		initProPageNavForSub: function (popHtml) {
			var participantsName = this._getOptions('participantsName');
			return  [
				{
					id:'base',
					name:this._getLang('menu.nodebase')//'基本属性'
				},
				{
					id: 'operator',
					name: this._getLang('menu.nodeoperator'),//'操作权限',
					sub:[
						{
							id:'oReader',
							name:participantsName['Reader'],//'读者',
							html:'actionform',
							page:['nodeAction','nodeForm']
						},
						{
							id:'oDone',
							name:participantsName['Done'],//'已办',
							html:'actionform',
							page:['nodeAction','nodeForm']
						},
						{
							id:'oManager',
							name:participantsName['Manager'],//'管理员',
							html:'actionform',
							page:['nodeAction','nodeForm']
						},
						{
							id:'oCreator',
							name:participantsName['Creator'],//'创建者',
							html:'actionform',
							page:['nodeAction','nodeForm']
						}
					]
				},
				{
					id: 'cluster',
					name: this._getLang('menu.nodecluster')//'交互设置'
				}
			];
		},


		initPropertiesDataSub:function(popWin,nodePro){
			popWin.find('#divNxtSelType :lt(3)').hide();

			var special = this.data.special;
			if(special){
				popWin.find('input[name="clusterInteractive"]').val(special['clusterInteractive']);
				popWin.find('input[name="clusterUrl"]').val(special['clusterUrl']);
				popWin.find('input[name="clusterClassName"]').val(special['clusterClassName']);
			}
			return "";
		},
		applyPropertiesData:function(popWin,data){
			data.special = {};
			data.special['clusterInteractive'] = popWin.find('input[name="clusterInteractive"]').val();
			data.special['clusterUrl'] = popWin.find('input[name="clusterUrl"]').val();
			data.special['clusterClassName'] = popWin.find('input[name="clusterClassName"]').val();
		}

	});
});
/**
 * 虚拟节点
 * @author liys 201903
 */
define('flowdesigner/element/node/VirtualNode',['require','../FlowNode'],function(require) {

	return require('../FlowNode').extend({

		id: 'Virtual',

		nodetype: '900',

		name: 'virtaul',
        isOnlyOneRoutNode: function () {
            return true;
        },
        isOnlyOneOutRouteNode: function () {
            return true;
        }

	});
});
/**
 * 子流程节点
 * @author liys 201903
 */
define('flowdesigner/element/node/SubflowNode',['require','zrender','../FlowNode'],function(require) {
    var zRender = require('zrender');

    return require('../FlowNode').extend({

        id: 'SubFlow',
        nodetype: '60',
        name: 'SubFlow',

        imageWidth:50,
        imageHeight:50,
        flowGroup:null,
        newImgShape:null,
        nodeGroup:['Node_Sub'],
        exceptions:['WFE_0120'],
        participants:['Reader'],
        operators:['Reader','Done','Manager','Creator'],
        eventTypeArr:[],

        getStatus:function(){
            return 'subflow';
        },
        isOnlyOneOutRouteNode: function () {
            return true;
        },
        //*
        // //子类重写的类
        // makeNodeShape:function(){
        //     var self = this;
        //     var color = this.__Flowdesigner.options.flownode.color;
        //     var stroke = color.define;
        //     var showtype = this.__Flowdesigner.showtype;
        //     if(showtype == 2){//流程跟踪
        //         if(this.data && this.data.showtype){
        //             switch(this.data.showtype){
        //                 case 'doneurl':
        //                     stroke = color.done;
        //                     break;
        //                 case 'nowurl':
        //                     stroke = color.now;
        //                     break;
        //                 case 'jumpurl':
        //                     stroke = color.jump;
        //                     break;
        //                 case 'waringurl':
        //                     stroke = color.extended;
        //                     break;
        //             }
        //         }
        //     }
        //     return new zRender.Rect({
        //         __node: this,
        //         z: self.__drawLayer.getZLevel(self.__Flowdesigner.zArr.node),
        //         scale: [1, 1],  //缩放比例
        //         origin:[0,0], //设置缩放中心
        //         position: [this.x  , this.y],
        //         style: {
        //             lineWidth: 2,
        //             fill: '#fff',
        //             stroke: stroke,
        //             lineDash:this.map['subflow']?null:[4 ,1],
        //             strokeNoScale:true, //描边粗细不随缩放而改变，false 则会根据缩放同比例缩放描边粗细。
        //             transformText:true, //文字是否跟随变换效果，仅对 Path 或 Image 元素有效
        //             text: this.name,
        //             textPosition: 'bottom',
        //             textAlign: 'center'
        //         },
        //         shape: {
        //             x: 0,
        //             y: 0,
        //             r: 5,
        //             width: self.imageWidth,
        //             height: self.imageHeight
        //         },
        //         draggable: (this.__Flowdesigner.showtype == 1||this.__Flowdesigner.showtype == 5)
        //     });
        // },
        // //动态修改节点显示,仅用于自动测试时
        // chgNodeShapeForTest:function(showtype){
        //     var color = this.__Flowdesigner.options.flownode.color;
        //     var stroke = color.define;
        //     switch(showtype){
        //         case 'doneurl':
        //             stroke = color.done;
        //             break;
        //         case 'nowurl':
        //             stroke = color.now;
        //             break;
        //         case 'jumpurl':
        //             stroke = color.jump;
        //             break;
        //         case 'waringurl':
        //             stroke = color.extended;
        //             break;
        //     }
        //
        //     this.nodeShape.attr({
        //         style:{
        //             stroke:stroke,
        //             lineDash:this.map['subflow']?null:[4 ,1]
        //         }
        //     });
        //
        // },
        //点击选中和取消状态
        // chgNodeShapeForClick:function(selected){
        //     var self = this;
        //     var z = self.__drawLayer.getZLevel(this.__Flowdesigner.zArr.node + (selected?1:0)); //加1是为了有重叠的时候,能把选中的显示在上面
        //     this.nodeShape.attr({
        //         z:z,
        //         style:{
        //             stroke: selected?'#2b9727':'#979797'
        //         }
        //     });
        //     if(this.newImgShape){
        //         this.newImgShape.attr({
        //             z:z
        //         });
        //     }
        //
        // },

        makeNewImg:function(DataURL,rectPoint){
            var self = this;
            var scale = self.__Flowdesigner.options['screenScale'] || 1;
            //point拷贝,避免原始数据被修改
            var point ={
                minX: rectPoint.minX,
                minY: rectPoint.minY,
                maxX: rectPoint.maxX,
                maxY: rectPoint.maxY
            };
            //如果电脑本身的显示被放大时,point的值需要修正
            if(scale !=1){
                point['minX'] *= scale;
                point['minY'] *= scale;
                point['maxX'] *= scale;
                point['maxY'] *= scale;
            }

            if(self.newImgShape){
                self.newImgShape.attr({
                    style:{
                        sx: point.minX ,
                        sy: point.minY ,
                        sWidth: (point.maxX - point.minX) ,
                        sHeight:(point.maxY - point.minY) ,

                        image: DataURL
                    }
                });
            }
            else{
                self.imageWidth = 50;
                self.imageHeight = 50;
                self.nodeShape.attr({
                    shape:{
                        width:self.imageWidth,
                        height:self.imageHeight
                    }
                });
                self._chgRelation();

                self.newImgShape = new zRender.Image({
                    __node: this,
                    z: self.__drawLayer.getZLevel(self.__Flowdesigner.zArr.node),
                    position: [self.x+1, self.y+1],
                    style: {
                        x: 0,
                        y: 0,
                       width: self.imageWidth-2,
                       height: self.imageHeight-2,
                        sx: point.minX ,
                        sy: point.minY ,
                        sWidth: (point.maxX - point.minX) ,
                        sHeight:(point.maxY - point.minY) ,

                        image: DataURL
                    },
                    draggable: (this.__Flowdesigner.showtype == 1)
                });
                self.bindEvent(self.newImgShape);
                self.zrGroup.add(this.newImgShape);
            }
        },
        getDragPoint:function(){
            if(this.newImgShape){
               return this.newImgShape.position;
            }
            else{
                return this.nodeShape.position;
            }
        },
        chgRelationExtend: function () {
            if(this.newImgShape) {
                this.newImgShape.attr({position:[this.x, this.y]});
            }
        },

        addOtherMenuItem:function (items) {
            if(this.map.subflow && this.__Flowdesigner.showtype ==1){
                items.push({
                    text: this.__Flowdesigner.getLang('menu.showsubflow'),//'显示子流程',
                    target:this,
                    fun: 'editSubFlow',
                    para: this.map.subflow  //子流程id(当前仅支持一个子流程吧)
                });
            }
        },
        editSubFlow:function (subflow) {
            var self = this;
            var keys = Object.keys(subflow);
            if(keys.length > 1){
                var html = '<select name="popSel" size="5" style="width:320px">';
                $.each(subflow,function(id,name){
                    if(name){
                        var showTxt = name+'('+id+')';
                        if(self.__Flowdesigner.showtype == 3){
                            showTxt += '[ '+self.data[id]['sumnum'] +' - '+ self.data[id]['warnnum']+' ]';
                        }
                        html += '<option value="'+id+'">'+showTxt+'</option>';
                    }
                });
                html += '</select>';
                this.__Flowdesigner.popSelWin(self._getLang('static.selsubflow'),html,//请选择一个子流程
                    function($this){
                    var id = $this.find('select[name="popSel"]').val();
                    if(id){
                        self.__Flowdesigner.loadSubData(id,self);
                    }
                    else{
                        self.__Flowdesigner.showMsg(self._getLang('static.selsubflow'));//请选择一个子流程
                        return false;
                    }
                });
            }
            else{
                this.__Flowdesigner.loadSubData(keys[0],this);
            }
        },
        showSubFlow:function () {
            this.editSubFlow(this.map.subflow);
        },

        addProMenuItem:function(items){
            items.push({
                text: this._getLang('menu.nodebase'),//'基本属性'
                target: this,
                fun: '_showProperties',
                para: 0
            });
            items.push({
                text: this._getLang('menu.nodeuser'),//'办理人设置'
                target: this,
                fun: '_showProperties',
                para: 1
            });
            items.push({
                text: this._getLang('menu.nodeoperator'),//'操作权限'
                target: this,
                fun: '_showProperties',
                para: 2
            });
            items.push({
                text: this._getLang('menu.nodesubflow'),//'子流程'
                target: this,
                fun: '_showProperties',
                para: 3
            });
            items.push({
                text: this._getLang('menu.nodeExtend'),//'扩展规则'
                target: this,
                fun: '_showProperties',
                para: 4
            });
            items.push({
                text: this._getLang('menu.nodeException'),//'异常处理'
                target: this,
                fun: '_showProperties',
                para: 5
            });
            items.push({
                text: this._getLang('menu.nodepara'),//'节点参数',
                target: this,
                fun: '_showProperties',
                para: 6
            });
        },

        //节点属性页签定义
        initProPageNavForSub: function (popHtml) {
            var participantsName = this._getOptions('participantsName');
            return  [
                {
                    id:'base',
                    name:this._getLang('menu.nodebase')//'基本属性'
                },
                {
                    id: 'participant',
                    name: this._getLang('menu.nodeuser'),//'办理人',
                    sub:[
                        {
                            id:'pReader',
                            name:participantsName['Reader'],//'读者',
                            html:'user',
                            page:['userOrg','userField','userVar','userRelation',
                                'userRule','userCustomer','sendMsg','control']
                        }
                    ]
                },
                {
                    id: 'operator',
                    name: this._getLang('menu.nodeoperator'),//'操作权限',
                    sub:[
                        {
                            id:'oReader',
                            name:participantsName['Reader'],//'读者',
                            html:'actionform',
                            page:['nodeAction','nodeForm']
                        },
                        {
                            id:'oDone',
                            name:participantsName['Done'],//'已办',
                            html:'actionform',
                            page:['nodeAction','nodeForm']
                        },
                        {
                            id:'oManager',
                            name:participantsName['Manager'],//'管理员',
                            html:'actionform',
                            page:['nodeAction','nodeForm']
                        },
                        {
                            id:'oCreator',
                            name:participantsName['Creator'],//'创建者',
                            html:'actionform',
                            page:['nodeAction','nodeForm']
                        }
                    ]
                },

                {
                    id: 'subflow',
                    name: this._getLang('menu.nodesubflow')//'子流程'
                },
                {
                    id: 'extendRule',
                    name:  this._getLang('menu.nodeExtend')//'扩展规则'
                },
                {
                    id: 'exception',
                    name:  this._getLang('menu.nodeException')//'异常处理'
                },
                {
                    id: 'nodePara',
                    name:  this._getLang('menu.nodepara')//'节点参数'
                }

            ];
        },

        initPropertiesDataSub:function(popWin,nodePro){

            this._initExtendRule(popWin);

            return "";
        },

        //扩展规则初始化
        _initExtendRule:function(popWin) {
            //进入
            this.bindRuleOrClass(popWin, 'entry', this.data.entry);

            popWin.find('.Node_Normal').html('');
        },

        //===========数据回写========================
        //确认属性框
        applyPropertiesData:function(popWin,data){
            data.entry = this.getRuleValue(popWin,'entry');

        }

    });
});

define('flowdesigner/element/properties/FlowProperties',['require','jquery','../FlowInit'],function (require) {
    var $ = require('jquery'),
        FlowInit = require('../FlowInit');

    var FlowProperties = function (opts, fd) {
        this.options = opts;
        this.__Flowdesigner = fd;
    };

    FlowProperties.prototype = {
        constructor: FlowProperties,
        __Flowdesigner: null,       //主对象
        tblObjArr: {},
        popHtml: null,
        chgForm: false,    //标记表单列表是否发生变化(删除,替换.增加不算)
        sortForm: false,     //标记表单进行了重新排序的变化

        _getLang: function (key) {
            return this.__Flowdesigner.getLang(key);
        },
        _getHtml: function (key) {
            return this.__Flowdesigner.getHtml(key);
        },
        _showMsg: function (msg, title, callback) {
            this.__Flowdesigner.showMsg(msg, title, callback);
        },
        _chgApplyBtn: function (applyBtn, disabled) {
            this.__Flowdesigner._chgApplyBtn(applyBtn, disabled);
        },
        _initPage: function () {
            var self = this;
            if (self.popHtml == null) {
                self.popHtml = $(self._getHtml('template/flow.html'));
                self.popHtml.find('#base').html(self._getHtml('template/flow/base.html'));
                self.popHtml.find('#form').html(self._getHtml('template/flow/form.html'));
                self.popHtml.find('#var').html(self._getHtml('template/flow/variable.html'));
                self.popHtml.find('#participant').html(self._getHtml('template/flow/reader.html'));
                self.popHtml.find('#reader').addClass('active');//二级标签
                self.popHtml.find('#senior').html(self._getHtml('template/flow/senior.html'));
            }
            return self.popHtml;
        },

        showProperties: function (data) {
            var self = this;
            var title = this._getLang('prop.title')
                .replace('name', data.flowName)
                .replace('id', data.flowId);
            this.__Flowdesigner.showPopWin({
                title: title,
                popHtml: self._initPage(),
                data: data,
                width: '950px',
                height: '435',
                initFun: function (popWin, data) {
                    return self._initPropertiesData(popWin, data);
                },
                applyFun: function (popWin, data) {
                    return self._applyPropertiesData(popWin, data);
                }
            });
        },
        _initPropertiesData: function (popWin, data) {
            this.tblObjArr = {};
            //-------基本属性---------
            this._initPropertiesData_Base(popWin, data);
            //-------表单属性---------
            this._initPropertiesData_From(popWin, data);
            //-------流程变量---------
            this._initPropertiesData_Var(popWin, data);
            //-------读者设置---------
            this._initPropertiesData_Reader(popWin, data);
            //-------高级属性---------
            this._initPropertiesData_Senior(popWin, data);

            return "";
        },
        //-------基本属性---------
        _initPropertiesData_Base: function (popWin, data) {
            var self = this;
            var fd = this.__Flowdesigner;
            //-------基本属性---------
            //只有在新建流程时，流程ID才可以修改
            var flowId = popWin.find('input[name="flowId"]');
            if (data.flowId == 'NewFlowId' || data.id == '') {
                //增加检测id是否已存在
                self.__Flowdesigner.checkAndChange(flowId,
                    'checkInputCharNumber', 32, function (value) {
                        self.__Flowdesigner.checkFlowIdIsExistFromServer(value);
                    });
            } else {
                flowId.attr('disabled', true);
            }

            flowId.val(data.flowId);
            popWin.find('input[name="flowName"]').val(data.flowName);
            var flowType = data['flowType'];
            popWin.find('input[name="flowType"]').val(flowType.name);
            popWin.find('input[name="flowTypeId"]').val(flowType.id);
            popWin.find('#btnSelFlowType').on('click', function () {
                //1.从后台获取分类列表
                fd.getFlowTypeFromServer(function (data) {
                    //2.弹出选择框
                    var html = '<div style="background-color: #F5F5F5">' +
                        '<ul id="tree" class="ztree" style="width:100%;height:300px; overflow:auto;"></ul>' +
                        '</div>';
                    //树的节点数据
                    var zNodes = fd.initTreeData(data['flowtypes'],
                        popWin.find('input[name="flowType"]').val());
                    // console.log(JSON.stringify(zNodes));
                    fd.popSelWin(self._getLang('prop.seltype'), html, //'请选择流程分类'
                        function ($this) {
                            var treeObj = $.fn.zTree.getZTreeObj("tree");
                            var nodes = treeObj.getSelectedNodes();
                            if (nodes.length == 0) {
                                self._showMsg(self._getLang('prop.seltype')); //'请选择分类'
                                return false;
                            }
                            var flowtype = [];
                            flowtype.push(nodes[0].name);
                            var pNode = nodes[0].getParentNode();
                            while (pNode != null) {
                                flowtype.push(pNode.name);
                                pNode = pNode.getParentNode();
                            }
                            flowtype.reverse();

                            popWin.find('input[name="flowType"]').val(flowtype.join('/'));
                            self._chgApplyBtn(popWin.find('#applyBtn'), false);
                        },
                        null, null,
                        function ($this) {
                            //初始化树
                            $.fn.zTree.init($this.$content.find("#tree"), {}, zNodes);
                        });
                });

            });

            var limitTime = popWin.find('input[name="limitTime"]');
            limitTime.val(data['flowlimit'].days);
            limitTime.on('keyup', function () {
                fd.checkInputOnlyNumber($(this));
            });

            //办理时限,类型列表初始化
            var limitType = popWin.find('select[name="limitType"]');
            fd.initSelectOptions(limitType, this.options.limitTypes, null, null, '' + data['flowlimit'].type);
            popWin.find(':radio[name="active"][value="' + data['active'] + '"]').prop("checked", "checked");
            popWin.find('input[name="updateToDB"]').prop("checked", data['updateToDB']);
            popWin.find('textarea[name="memo"]').val(data['memo']);
        },

//-------表单属性---------
        _initPropertiesData_From: function (popWin, data) {
            var self = this;
            var fd = this.__Flowdesigner;
            //表格参数准备
            var items = [];
            $.each(data.forms || [], function (key, form) {
                if (form) {
                    items.push(form);
                }
            });

            //表单 tblFlowForm
            var tblFlowForm = popWin.find('#tblFlowForm').mmGrid({
                height: 225
                ,delTitle:self._getLang('table.field.defTitle')
                ,showCol:self._getLang('table.field.showCol')
                , cols: self._getFlowFormTableCol()
                , items: items      //本地数据
                , nowrap: true
                , multiSelect: true
                , fullWidthRows: true
                , autoLoad: false
                , loadingText: self._getLang('html.flow.form.table.load')//'正在加载表单列表...'
                , noDataText: self._getLang('html.flow.form.table.nodata')//'请添加流程需要的表单'
            });
            //加载表格
            tblFlowForm.load();
            this.tblObjArr['tblFlowForm'] = tblFlowForm;
            //  初始化时更新主表单列表
            self._chgMainFormSelect(popWin, tblFlowForm, false);

            popWin.find('#btnAddForm').on('click', function () {
                self._initPopForm(popWin, tblFlowForm, true);
            });
            popWin.find('#btnRplForm').on('click', function () {
                if (tblFlowForm.selectedRowsIndex().length > 0) {
                    if (tblFlowForm.selectedRows()[0]['id'] == 'FlowTrack') {
                        self._showMsg(self._getLang('html.flow.form.table.trackform'));//'流程跟踪是内置表单不可替换');
                        return;
                    }
                    if (tblFlowForm.selectedRows().length > 1) {
                        self._showMsg(self._getLang('html.flow.form.table.selrplformonly'));//'流程跟踪是内置表单不可替换');
                        return;
                    }
                    self._initPopForm(popWin, tblFlowForm, false);
                } else {
                    self._showMsg(self._getLang('html.flow.form.table.selrplform'));//'请从列表中选择要替换的表单');
                }
            });
            popWin.find('#btnAddTrack').on('click', function () {
                var isHaveTrack = false;
                $.each(tblFlowForm.rows() || [], function (i, item) {
                    if (item && item.id == 'FlowTrack') {
                        isHaveTrack = true;
                        return self.BREAK;
                    }
                });
                if (isHaveTrack) {
                    return;
                }
                //判断是否已经存在流程跟踪
                tblFlowForm.addRow({
                    id: 'FlowTrack',
                    name: self._getLang('html.flow.form.table.trackname')//'流程跟踪'
                });
                tblFlowForm.deselect('all');
                tblFlowForm.select(tblFlowForm.rowsLength() - 1);
                self._chgMainFormSelect(popWin, tblFlowForm, true);
            });
            popWin.find('#btnDelForm').on('click', function () {
                if (fd.delCheckSel(tblFlowForm)) {
                    return;
                }
                fd.applyQuestion(self._getLang('html.flow.form.table.del'), function () {
                    self.chgForm = true;
                    tblFlowForm.removeRow(tblFlowForm.selectedRowsIndex());
                    self._chgMainFormSelect(popWin, tblFlowForm, true);
                });
            });
            popWin.find('#btnDelFormAll').on('click', function () {
                fd.applyQuestion(self._getLang('html.flow.form.table.delAll'), function () {
                    tblFlowForm.removeRow();
                    self.chgForm = true;
                    self._chgMainFormSelect(popWin, tblFlowForm, true);
                });
            });
            popWin.find('#btnUp').on('click', function () {
                self._chgTableDataUpDown(tblFlowForm, true);
                self._chgMainFormSelect(popWin, tblFlowForm, true);
                self.sortForm = true;
            });
            popWin.find('#btnDown').on('click', function () {
                self._chgTableDataUpDown(tblFlowForm, false);
                self._chgMainFormSelect(popWin, tblFlowForm, true);
                self.sortForm = true;
            });

            popWin.find('#selectMainForm').on('change', function () {
                var mId = $(this).val();
                $.each(tblFlowForm.rows() || [], function (i, item) {
                    if (!item) {
                        return fd.CONTINUE;
                    }
                    if (item.id == mId) {
                        item.isMain = 1;
                    } else {
                        item.isMain = 0;
                    }
                });
                self.sortForm = true;
            });

        },
        _initPopForm: function (popWin, tblFlowForm, isAdd) {
            var self = this;
            var fd = this.__Flowdesigner;
            fd.getFormsFromServer(function (data) {
                var formIds = ''; //已有表单id字符串,用于判断
                var forms = data.forms;//系统返回的所有表单列表
                var allForms = tblFlowForm.rows();
                $.each(allForms || [], function (i, item) {
                    if (item) {
                        formIds += item.id + ';';
                    }
                })
                var pages = [];
                var groups = [];
                //转换为ztree格式数据
                if (forms) {
                    $.each(forms || [], function (i, item) {
                        if (formIds.indexOf(item.data) != -1) {
                            return fd.CONTINUE;//continue;
                        }
                        if (!item.type) {
                            item.type = "未分类";
                        }
                        var page = {};
                        page.id = item.data;
                        page.name = item.label;
                        page.label = item.label + "(" + item.data + ")";
                        page.parentId = item.type;
                        pages.push(page);
                        if (groups.indexOf(item.type) == -1) {
                            var page = {};
                            page.id = item.type;
                            page.label = item.type;
                            page.parentId = "";
                            groups.push(item.type)
                            pages.push(page);
                        }
                    })
                    if (pages.length <= 0) {
                        self._showMsg(self._getLang('html.flow.form.table.noOptionsform'));
                        return;
                    }
                }
                var html = '<div style="background-color: #F5F5F5">' +
                    '<ul id="tree" class="ztree" style="width:100%;height:300px; overflow:auto;"></ul></div>';
                var allForms = tblFlowForm.rows();//当前已经选择的表单列表
                var formIds = [];                   //已有表单id字符串,用于判断
                $.each(allForms || [], function (i, item) {
                    if (item) {
                        formIds.push(item.id);
                    }
                });
                var treeObj;
                fd.popSelWin(self._getLang('html.flow.form.table.selform'), html,
                    function ($this) {
                        var selectedNode = treeObj.getSelectedNodes();
                        if (selectedNode)
                            var selObj = selectedNode[0];

                        var formIds = '', formNames = {};
                        var allsel = [selObj.id];
                        $.each(allsel || [], function (i, id) {
                            if (!id) {
                                return fd.CONTINUE;
                            }
                            //判断是否已经获取过
                            if (!fd.curDrawLayer.forms[id]) {
                                formIds += id + ';';
                                formNames[id] = selObj.name;
                            }

                            var option = forms[id];//selObj.find('option[value="' + id + '"]');
                            var form = FlowInit.initFlowForm();
                            form.id = id;
                            form.name = option.label;
                            form.tableId = option.table;
                            form.type = option.type;
                            form.version = option.version;
                            form.isMain = 0;
                            form.group = '';
                            if (isAdd) {
                                tblFlowForm.addRow(form);
                            } else {
                                //替换
                                var index = tblFlowForm.selectedRowsIndex()[0];
                                var oldForm = tblFlowForm.row(index);
                                form.isMain = oldForm.isMain;
                                form.group = oldForm.group;
                                //只记录第一次更换时的表单ID,不能记录每次变化的值,避免出现同一表单反复替换时,丢失节点中实际使用的表单ID
                                form['oldId'] = oldForm['oldId'] || oldForm.id;

                                tblFlowForm.updateRow(form, index);
                                self.chgForm = true;
                            }

                        });
                        if (formIds) {
                            //从服务器获取表单的信息
                            fd.getFormInfoFromServer(formIds, formNames, self.tblObjArr['tblFlowVar']);
                        }

                        self._chgMainFormSelect(popWin, tblFlowForm, true);
                    }, "500px", null, function ($this) {
                        var selectedNode = [];
                        //初始化树
                        treeObj = $.fn.zTree.init($this.$content.find("#tree"), {
                            view: {
                                showIcon: false,
                                showLine: false,
                                showTitle: false,
                                selectedMulti: false
                            },
                            data: {
                                key: {
                                    name: "label", //
                                    children: "children", //zTree 节点数据中保存子节点数据的属性名称。
                                    isParent: "isParent", //zTree 节点数据保存节点是否为父节点的属性名称。
                                },
                                keep: {
                                    parent: true,
                                    leaf: true,
                                },
                                simpleData: {
                                    enable: true, // 显示层级
                                    idKey: "id", // 唯一标识的属性名称
                                    pIdKey: "parentId", // 父节点唯一标识的属性名称
                                    rootPId: 0, // 修正根节点父节点数据
                                },
                            },
                            click: {
                                enable: true
                            },
                            callback: {
                                beforeClick: function (treeId, treeNode) {
                                    if (treeNode.children) {
                                        return false;
                                    }
                                }
                            }
                        }, pages);
                        treeObj.expandAll(true);
                        for (var i = 0; i < formIds.length; i++) {
                            treeObj.selectNode(treeObj.getNodeByTId(formIds[i]), true, false);
                        }
                    });
            });
        },

        //表单页签中的表格列定义
        _getFlowFormTableCol: function () {
            var title = this._getLang('html.flow.form.table.title');
            return [
                {
                    title: title[0],//'名称',
                    name: 'name',
                    width: 324,
                    lockWidth: true
                }
                , {
                    title: title[1],//'ID',
                    name: 'id',
                    width: 330,
                    lockWidth: true
                }
                , {
                    title: title[2],//'类型',
                    name: 'type',
                    width: 80,
                    lockWidth: true,
                    align: 'center',
                    lockWidth: true
                }
                , {
                    title: title[3],//'版本',
                    name: 'version',
                    width: 60,
                    lockWidth: true,
                    align: 'right'
                    // sortable: true,
                }
                , {
                    title: title[4],//'分组',
                    name: 'group',
                    width: 100,
                    lockWidth: true,
                    align: 'center',
                    autoLoad: false,
                    renderer: function (val, item, rowIndex) {
                        return '<input type="text" name="group_' + rowIndex + '" value="' + (val ? val : '') + '" class="form-control checkChange">'
                    }
                    // sortable: true,
                }
            ];
        },
        //表格数据上下移动处理
        _chgTableDataUpDown: function (tblObj, isUp) {
            this.__Flowdesigner.chgTableDataUpDown(tblObj, isUp);
        },
        //下拉框数据初始化
        _chgMainFormSelect: function (popWin, tblObj, isChg) {
            var mainSelect = popWin.find('#selectMainForm');
            var varFormSelect = popWin.find('select[name="formlst"]');//流程变量页签使用的表单列表
            var varFieldSelect = popWin.find('select[name="fieldlst"]');
            //获取所有数据行
            var allItems = tblObj.rows();

            //5.根据所有数据行,重新生成下拉列表
            mainSelect.empty();
            varFormSelect.empty();
            varFieldSelect.empty();
            mainSelect.append('<option value="">' + this._getLang('prop.selmainform') + '</option>');//请选择一个表单作为主表单
            varFormSelect.append('<option value="">' + this._getLang('prop.selform') + '</option>');//请指定表单
            varFieldSelect.append('<option value="">' + this._getLang('prop.selfield') + '</option>');//请指定字段
            var len = allItems.length;
            var fd = this.__Flowdesigner;
            $.each(allItems || [], function (i, item) {
                if (item) {
                    if (len > 1 && item.id == 'FlowTrack') {
                        //如果表单多于一个时,不显示流程跟踪
                        return fd.CONTINUE;
                    }
                    mainSelect.append('<option value="' + item.id + '" ' +
                        (item.isMain == 1 ? 'selected' : '')
                        + '>' + item.name + '</option>');
                    if (item.id != 'FlowTrack') {
                        varFormSelect.append('<option value="' + item.id + '">' + item.name + '</option>');
                    }
                }
            });

            if (isChg) {
                this._chgApplyBtn(popWin.find('#applyBtn'), false);
            }
        },

//-------流程变量---------
        _initPropertiesData_Var: function (popWin, data) {
            var self = this;
            //表格参数准备
            var items = [];
            $.each(data.vars || [], function (key, vv) {
                if (vv) {
                    items.push(vv);
                }
            });
            var varType = popWin.find('select[name="varType"]');
            self.__Flowdesigner.initSelectOptions(varType, this.options.varTypes);

            popWin.find('input[name="varId"]').on('keyup', function () {
                self.__Flowdesigner.checkInputCharNumber($(this));
            });
            popWin.find('input[name="varLen"]').on('keyup', function () {
                self.__Flowdesigner.checkInputOnlyNumber($(this));
            });
            var tblFlowVar = popWin.find('#tblFlowVar').mmGrid({
                height: 160
                ,delTitle:self._getLang('table.field.defTitle')
                ,showCol:self._getLang('table.field.showCol')
                , cols: this._getFlowVarTableCol(popWin)
                , items: items      //本地数据
                // , method: 'get'
                // , remoteSort:true

                , multiSelect: true
                , fullWidthRows: true
                , autoLoad: false
                , loadingText: self._getLang('html.flow.var.table.load')//'正在加载流程变量列表...'
                , noDataText: self._getLang('html.flow.var.table.nodata')//'请添加流程变量'
            });
            //加载表格
            tblFlowVar
                .on('cellSelected', function (e, item, rowIndex, colIndex) {
                    //判断当前数据是否被选中
                    var selectIndex = tblFlowVar.selectedRowsIndex();
                    if (selectIndex[0] == rowIndex) {
                        //取消选中
                        self._cancelVarSel(popWin);
                    } else {
                        popWin.find('input[name="varId"]').val(item.varId);
                        popWin.find('input[name="varName"]').val(item.varName);
                        varType.val(item.varType);
                        popWin.find('input[name="varLen"]').val(item.len);
                        popWin.find('input[name="initValue"]').val(item.initValue);
                        popWin.find('input[name="memo"]').val(item.memo);

                        var formSelect = popWin.find('select[name="formlst"]');
                        if (item.varFrom) {
                            var pageId = item.pageId;
                            var fieldId = item.varFrom;
                            formSelect.val(pageId);
                            formSelect.change();
                            if (popWin.find('select[name="fieldlst"]').find('option[value="' + fieldId + '"]').length == 0) {
                                fieldId = pageId + '_' + fieldId.substring(fieldId.indexOf('_') + 1, fieldId.length);
                            }
                            popWin.find('select[name="fieldlst"]').val(fieldId);
                        } else {
                            formSelect.val('');
                            formSelect.change();
                        }
                        popWin.find('#btnVarAdd').text(self._getLang('prop.apply'));//'应用');
                    }
                })
                .load();
            //记录表格对象,为确认保存数据使用
            this.tblObjArr['tblFlowVar'] = tblFlowVar;

            popWin.find('select[name="formlst"]').on('change', function () {
                self.__Flowdesigner.initFieldSelect(popWin.find('select[name="fieldlst"]'), $(this).val());
            });
            popWin.find('#btnVarAdd').on('click', function () {
                if (popWin.find('input[name="varId"]').val() == '') {
                    self._showMsg(self._getLang('html.flow.var.table.idnull'));//'变量ID不能为空');
                    return;
                }
                var selIndex = tblFlowVar.selectedRowsIndex();
                var allRows = tblFlowVar.rows();

                if (selIndex.length == 1) {
                    var selItem = tblFlowVar.selectedRows();
                    var oldId = selItem[0]['varId'];
                    var item = self._makeVarItem(popWin, allRows, oldId);
                    if (item == null) {
                        self._showMsg(self._getLang('html.flow.var.table.chgidexist'));//'修改后的变量ID已经存在');
                        return;
                    }
                    tblFlowVar.updateRow(item, selIndex[0]);
                    //取消选中
                    tblFlowVar.deselect('all');
                } else {
                    var item = self._makeVarItem(popWin, allRows, null);
                    if (item == null) {
                        self._showMsg(self._getLang('html.flow.var.table.idexist'));//'变量ID已经存在');
                        return;
                    }
                    tblFlowVar.addRow(item);
                }
                //清空输入区域(不论是应用还是添加,点击后都清空)
                self._cancelVarSel(popWin);
                self._chgApplyBtn(popWin.find('#applyBtn'), false);
            });
            popWin.find('#btnVarDel').on('click', function () {
                if (self.__Flowdesigner.delCheckSel(tblFlowVar)) {
                    return;
                }
                self.__Flowdesigner.applyQuestion(self._getLang('html.flow.var.table.del'), function () {
                    tblFlowVar.removeRow(tblFlowVar.selectedRowsIndex());
                    self._cancelVarSel(popWin);
                    self._chgApplyBtn(popWin.find('#applyBtn'), false);
                });
            });
            popWin.find('#btnVarDelAll').on('click', function () {
                self.__Flowdesigner.applyQuestion(self._getLang('html.flow.var.table.delAll'), function () {
                    tblFlowVar.removeRow();
                    self._cancelVarSel(popWin);
                    self._chgApplyBtn(popWin.find('#applyBtn'), false);
                });
            });

        },
        _makeVarItem: function (popWin, allItem, ignoreId) {
            var isHave = false;
            var newId = popWin.find('input[name="varId"]').val();
            if (newId == '') {
                return null;
            }
            var fd = this.__Flowdesigner;
            $.each(allItem || [], function (i, item) {
                if (item && item['varId'] != ignoreId && item['varId'] == newId) {
                    isHave = true;
                    return fd.BREAK;
                }
            });
            if (isHave) {
                return null;
            }
            var item = {};
            item['varId'] = newId;
            item['varName'] = popWin.find('input[name="varName"]').val();
            item['varType'] = parseInt(popWin.find('select[name="varType"]').val());
            item['len'] = popWin.find('input[name="varLen"]').val();
            item['initValue'] = popWin.find('input[name="initValue"]').val();
            item['memo'] = popWin.find('input[name="memo"]').val();
            item['pageId'] = popWin.find('select[name="formlst"]').val();
            var fieldId = popWin.find('select[name="fieldlst"]').val();
            if (fieldId && fieldId != "") {
                item['varFrom'] = fieldId;
            } else {
                item['varFrom'] = "";
            }
            return item;
        },
        _cancelVarSel: function (popWin) {
            //取消选中
            popWin.find('input[name="varId"]').val("");
            popWin.find('input[name="varName"]').val("");
            popWin.find('select[name="varType"]').val("1");
            popWin.find('input[name="varLen"]').val("");
            popWin.find('input[name="initValue"]').val("");
            popWin.find('input[name="memo"]').val("");

            var formSelect = popWin.find('select[name="formlst"]');
            formSelect.val("");
            formSelect.change();
            popWin.find('select[name="fieldlst"]').val("");

            popWin.find('#btnVarAdd').text(this._getLang('prop.add'));//'添加');
        },

        _getFlowVarTableCol: function (popWin) {
            var self = this;
            var title = this._getLang('html.flow.var.table.title');
            var fd = this.__Flowdesigner;
            return [
                {
                    title: title[0],//'ID',
                    name: 'varId',
                    width: 85,
                },
                {
                    title: title[1],//'名称',
                    name: 'varName',
                    width: 200,
                    // align: 'left',
                    // sortable: true,
                },
                {
                    title: title[2],//'类型',
                    name: 'varType',
                    width: 80,
                    lockWidth: true,
                    renderer: function (val, item, rowIndex) {
                        return fd.getLabelFromList(self.options.varTypes, val);
                    }
                },
                {
                    title: title[3],//'长度',
                    name: 'len',
                    width: 60,
                    lockWidth: true
                },
                {
                    title: title[4],//'初始值',
                    name: 'initValue',
                    width: 100,
                    lockWidth: true
                },
                {
                    title: title[5],//'数据来源',
                    name: 'varFrom',
                    width: 215,
                    nowrap: true,
                    renderer: function (val, item, rowIndex) {
                        if (val != '') {
                            var result = val;
                            var pageId = item.pageId;
                            if (!pageId) {
                                pageId = val.substr(0, val.indexOf("_"));
                            }
                            var form = self.__Flowdesigner.curDrawLayer.forms[pageId];
                            if (form) {
                                //从表单字段列表中获取
                                $.each(form && form['fields'] || [],
                                    function (key, value) {
                                        if (key == value[1]) {
                                            return fd.BREAK;
                                        }
                                    });
                                var field = form['fields']['mixed_' +val];
                                if(!field){
                                    field = form['fields'][val];
                                }
                                if (!field) {
                                    field = form['fields']['mixed_' + pageId + '_' + val.substring(val.indexOf('_') + 1, val.length)];
                                }
                                if (!field) {
                                    field = val.substr(val.indexOf("_") + 1);
                                }
                                field = field.split("&")[1];
                                result = form.name + '_' + field;
                            } else {
                                var forms = self.tblObjArr['tblFlowForm'].rows();
                                $.each(forms, function (i, form) {
                                    if (form.id == pageId) {
                                        result = form.name + '_' + val;
                                        return fd.BREAK;
                                    }
                                })
                            }
                            return result;
                        }
                    }

                },
                {
                    title: title[6],//'说明',
                    name: 'memo',
                    width: 150,
                    lockWidth: true
                }

            ];
        },

//-------读者设置---------
        _initPropertiesData_Reader: function (popWin, data) {
            var self = this;
            //表格参数准备(包含获取中文名称,异步处理,不等待结果返回)
            this.initOrgData(
                data.participants['Reader'], popWin, this.tblObjArr, 'tblReader', 270, true);
        },
        initOrgData: function (userdata, userOrg, tblObjArr, key, height, async, callback) {
            /*
            var self = this;
            var orgTypes = this.options.orgTypes;
            var items = [];
            //数据初始化
            var orgs = {};
            $.each(userdata || [],function(key,item){
                //从json数据中的participants节点获取,下面的标示不要修改,
                if(item &&(key == 'person' || key == 'dept' || key == 'group' || key == 'position')){
                    $.each(item.split(";") || [], function (i, org) {
                        if(org){
                            //org 拆分
                            if(key =='person'){
                                self._splitOrg(orgs,org);
                            }
                            else{
                                var index = org.indexOf('_');
                                self._pushToJson(orgs,key,org.substring(index+1));
                            }
                            items.push({
                                data: org,
                                label: org,
                                typeCn: orgTypes[key],
                                type:key
                            });
                        }
                    });
                }
            });
            this._initOrgNamesFromServer(orgs,function(){
                // callback(items);
                //userOrg 标签内的表格对象获取
                var tblUserOrg = userOrg.find('#tblUserOrg').mmGrid({
                    height: height
                    , cols: self._getUserOrgTableCol()
                    , items: items      //本地数据
                    , nowrap:true
                    , multiSelect: true
                    , fullWidthRows: true
                    , autoLoad: false
                    , loadingText:self.getLang('html.org.load')
                    , noDataText:self.getLang('html.org.nodata')
                });
                tblUserOrg
                    .on('cellSelected', function (e, item, rowIndex, colIndex) {
                        if ($(e.target).is('.selBtn')) {
                            e.stopPropagation(); //阻止事件冒泡
                            var d = item.data;
                            var label = '';
                            var title = self.getLang('html.org.title');
                            if(d.startsWith('D_')){
                                d = 'S'+d.substring(1);
                                label = title[4];
                            }
                            else{
                                d = 'D'+d.substring(1);
                                label = title[3];
                            }
                            item.data = d;
                            $(e.target).html(label);
                            tblUserOrg.updateRow(item,rowIndex);
                            self._chgApplyBtn();
                        }
                    })
                    .on('loadSuccess',function(e, data){
                        userOrg.find('.deptTypeSel').on('change',function(){
                            var rowIndex = $(this).parent().parent().parent().index();
                            var item = tblUserOrg.row(rowIndex);
                            var tmp = item.data;
                            var pos = tmp.indexOf('_') + 1;
                            item.data= $(this).val() +'_' + tmp.substring(pos);
                            tblUserOrg.load(tblUserOrg.rows());
                            self._chgApplyBtn($('#applyBtn'), false);
                        });
                    })
                    .load();
                tblObjArr[key] = tblUserOrg;
                //按钮事件绑定
                userOrg.find('#btnOrgAdd').on('click',function(){
                    var org = {data:'',label:''};
                    $.each(tblUserOrg.rows() || [],function(i,item){
                       if(item){
                           org['data'] += item.data +';';
                           org['label'] += item.label +';';
                       }
                    });

                    $('#hzPopModal').hide();
                    selectUser(org,function(data){
                        if(data){
                            var ids = data.data.split(';');
                            var name = data.label.split(';');
                            var items = [];
                            var keys ={
                                U:'person',
                                D:'dept',
                                S:'dept',
                                G:'group',
                                P:'position'
                            };
                            $.each(ids || [],function(i,value){
                                if(!value){return self.CONTINUE;} //continue
                                //是否有前缀，如果没有默认为U
                                var pos = value.indexOf('_');
                                var key = keys['U'];
                                if(pos == 1){
                                    key = keys[value.substring(0,1)];//获取前缀对应的标识
                                    value = value;//.substring(2);      //重置value值
                                }
                                items.push({
                                    data: value,
                                    label: name[i],
                                    typeCn: orgTypes[key],
                                    type:key
                                });
                                //选择后的组织信息缓存到orgCnNames中
                                self._pushToCnNames(value,name[i]);

                            });
                        }
                        tblUserOrg.load(items);
                        self._chgApplyBtn();
                        $('#hzPopModal').show();
                    });

                });
                userOrg.find('#btnOrgDel').on('click',function(){
                    if(self.delCheckSel(tblUserOrg)){
                        return;
                    }
                    self.applyQuestion(self.getLang('html.org.del'),function() {
                        tblUserOrg.removeRow(tblUserOrg.selectedRowsIndex());
                        self._chgApplyBtn($('#applyBtn'), false);
                    });
                });
                userOrg.find('#btnOrgDelAll').on('click',function(){
                    self.applyQuestion(self.getLang('html.org.delAll'),function() {
                        tblUserOrg.removeRow();
                        self._chgApplyBtn($('#applyBtn'), false);
                    });
                });
            },async);
            //*/
            this.initOrgDataTable(userOrg, tblObjArr, key, height, callback);
            this.__Flowdesigner.initOrgDataItem(userdata, tblObjArr, key, async);
        },
        initOrgDataTable: function (userOrg, tblObjArr, key, height, callback) {
            var self = this.__Flowdesigner;
            var orgTypes = this.options.orgTypes;
            var tblUserOrg = userOrg.find('#tblUserOrg').mmGrid({
                height: height
                ,delTitle:self.getLang('table.field.defTitle')
                ,showCol:self.getLang('table.field.showCol')
                , cols: this._getUserOrgTableCol()
                , items: []      //本地数据
                , nowrap: true
                , multiSelect: true
                , fullWidthRows: true
                , autoLoad: false
                , loadingText: self.getLang('html.org.load')
                , noDataText: self.getLang('html.org.nodata')
            });
            tblUserOrg
                .on('cellSelected', function (e, item, rowIndex, colIndex) {
                    if ($(e.target).is('.selBtn')) {
                        e.stopPropagation(); //阻止事件冒泡
                        var d = item.data;
                        var label = '';
                        var title = self.getLang('html.org.title');
                        if (d.startsWith('D_')) {
                            d = 'S' + d.substring(1);
                            label = title[4];
                        } else {
                            d = 'D' + d.substring(1);
                            label = title[3];
                        }
                        item.data = d;
                        $(e.target).html(label);
                        tblUserOrg.updateRow(item, rowIndex);
                        self._chgApplyBtn();
                    }
                })
                .on('loadSuccess', function (e, data) {
                    userOrg.find('.deptTypeSel').on('change', function () {
                        var rowIndex = $(this).parent().parent().parent().index();
                        var item = tblUserOrg.row(rowIndex);
                        var tmp = item.data;
                        var pos = tmp.indexOf('_') + 1;
                        item.data = $(this).val() + '_' + tmp.substring(pos);
                        tblUserOrg.load(tblUserOrg.rows());
                        if (callback) {
                            callback();
                        }
                        self._chgApplyBtn($('#applyBtn'), false);
                    });
                })
                .load();
            tblObjArr[key] = tblUserOrg;
            //按钮事件绑定
            userOrg.find('#btnOrgAdd').on('click', function () {
                var org = {data: '', label: ''};
                $.each(tblUserOrg.rows() || [], function (i, item) {
                    if (item) {
                        org['data'] += item.data + ';';
                        org['label'] += item.label + ';';
                    }
                });

                $('#hzPopModal').hide();
                selectUser(org, function (data) {
                    if (data) {
                        var ids = data.data.split(';');
                        var name = data.label.split(';');
                        var items = [];
                        var keys = {
                            U: 'person',
                            D: 'dept',
                            S: 'dept',
                            G: 'group',
                            P: 'position'
                        };
                        $.each(ids || [], function (i, value) {
                            if (!value) {
                                return self.CONTINUE;
                            } //continue
                            //是否有前缀，如果没有默认为U
                            var pos = value.indexOf('_');
                            var key = keys['U'];
                            if (pos >= 1) {
                                key = keys[value.substring(0, 1)];//获取前缀对应的标识
                                value = value;//.substring(2);      //重置value值
                            }
                            items.push({
                                data: value,
                                label: name[i],
                                typeCn: orgTypes[key],
                                type: key
                            });
                            //选择后的组织信息缓存到orgCnNames中
                            self._pushToCnNames(value, name[i]);

                        });
                    }
                    tblUserOrg.load(items);
                    if (callback) {
                        callback('add');
                    }
                    self._chgApplyBtn();
                    $('#hzPopModal').show();
                });

            });
            userOrg.find('#btnOrgDel').on('click', function () {
                if (self.delCheckSel(tblUserOrg)) {
                    return;
                }
                self.applyQuestion(self.getLang('html.org.del'), function () {
                    tblUserOrg.removeRow(tblUserOrg.selectedRowsIndex());
                    if (callback) {
                        callback('del');
                    }
                    self._chgApplyBtn($('#applyBtn'), false);
                });
            });
            userOrg.find('#btnOrgDelAll').on('click', function () {
                self.applyQuestion(self.getLang('html.org.delAll'), function () {
                    tblUserOrg.removeRow();
                    if (callback) {
                        callback('delAll');
                    }
                    self._chgApplyBtn($('#applyBtn'), false);
                });
            });
        },
        _getUserOrgTableCol: function () {
            var self = this.__Flowdesigner;
            var title = self.getLang('html.org.title');
            var deptTypes = self.getOptions('deptTypes');

            var selHtml = function (sel) {
                var tmpHtml = '<select style="width:80px" class="deptTypeSel">';
                $.each(deptTypes || [], function (data, label) {
                    tmpHtml += '<option value="' + data + '" ' + (sel == data ? 'selected="selected"' : '') + '>' + label + '</option>';
                });
                tmpHtml += '</select>';
                return tmpHtml;
            }

            return [
                {
                    title: title[0],//'组织名称',
                    name: 'label',
                    width: 400,
                    sortable: true,
                    align: 'left',
                    renderer: function (val, item, rowIndex) {
                        if (val == item.data) {
                            //直接查找一次，如果存在说明是刚选择的组织（没有保存重新打开流程时）
                            var label = self.getCnName(val);
                            if (!label) {
                                //如果没有值，则继续拆分查找
                                var orgs = val.split('/');
                                var suf = '';
                                if (orgs.length > 1) {
                                    suf = ('(' + self.getCnName(orgs[1]) + ')');
                                }

                                label = self.getCnName(orgs[0]) + suf;
                            }

                            item.label = label;
                            return label;
                        } else {//从前台选择返回时,不需要组合
                            return val;
                        }
                    }
                },
                {
                    title: title[1],//'组织ID',
                    name: 'data',
                    width: 300,
                    sortable: true,
                    align: 'center',
                    renderer: function (val, item, rowsIndex) {
                        return '<span title="' + val + '">' + val + '</span>';
                    }
                },
                {
                    title: title[2],//'类型',
                    name: 'typeCn',
                    width: 180,
                    sortable: true,
                    align: 'center',
                    renderer: function (val, item, rowsIndex) {
                        var html = val;
                        var data = item['data'];
                        var sel = data.substring(0, data.indexOf('_'));
                        if (data.startsWith('S') || data.startsWith('D')) {
                            //html = '<button class="btn btn-info btn-sm pull-right selBtn">'+title[4]+'</button>';
                            html = selHtml(sel);
                        }

                        return html;
                    }
                }
            ];
        },
//-------高级属性---------
        _initPropertiesData_Senior: function (popWin, data) {
            popWin.find('select[name="openTodoFlag"]').val(data.openTodoFlag);
            popWin.find('input[name="startRuleClassName"]').val(data.startRuleClassName);
            popWin.find('input[name="checkRoleClassName"]').val(data.checkRoleClassName);
            popWin.find('input[name="trackLogClassName"]').val(data.trackLogClassName);
            popWin.find('input[name="relationRuleClassName"]').val(data.relationRuleClassName);
        },

        //点击应用或者确定时,把数据更新到data中
        _applyPropertiesData: function (popWin, data) {
            var self = this;
            var oldName = data.flowName;//用于更新泳道标题时判断
            var oldId = data.flowId;
            var flowId = popWin.find('input[name="flowId"]');
            var flowName = popWin.find('input[name="flowName"]');
            var mapData = self.__Flowdesigner.curDrawLayer.data['mapData']; //更新map数据中的flowId和flowName

            if (flowId.val() == '') {
                return self._getLang('prop.flowidnull');
            }
            function isNull( str ){
                if ( str == "" ) return true;
                var regu = "^[ ]+$";
                var re = new RegExp(regu);
                return re.test(str);
            }
            if (isNull(flowName.val())) {
                return self._getLang('prop.flowNameNull');
            }
            if (flowName.val().length > 200) {
                return self._getLang('prop.flowNameLength');
            }
            if (flowId.val() == 'NewFlowId') {
                return self._getLang('prop.chgflowid');//'请修改流程ID为非默认值');
            } else {
                if (!self.__Flowdesigner.isSaveFlow) {
                    return flowId.val() + self._getLang('prop.flowexist');
                }
                data.flowId = flowId.val();
                if (data.id == '') {
                    //重置当前层的flowid,避免新建流程保存后的不一致
                    self.__Flowdesigner.curDrawLayer.flowid = data.flowId;
                    //新创建流程,第一次修改flowid后确认
                    //新创建流程,一定是主流程
                    self.__Flowdesigner.flowid = data.flowId;
                    self.__Flowdesigner.dataid = data.flowId;

                    delete self.__Flowdesigner.drawLayers[oldId];
                    self.__Flowdesigner.drawLayers[data.flowId] = self.__Flowdesigner.curDrawLayer;
                    //mapData中的flowId和flowName也是需要同步更新,否则再次打开会有问题的
                    mapData['flowId'] = data.flowId; ////更新mapData中的flowId对应的数据,仅在新建时执行一次
                }
                if (data.id != '') {
                    flowId.attr('disabled', true);
                }
            }

            data.flowName = popWin.find('input[name="flowName"]').val();
            mapData['flowName'] = data.flowName; //更新mapData中的flowName对应的数据

            data.flowType['name'] = popWin.find('input[name="flowType"]').val();
            data.flowType['id'] = popWin.find('input[name="flowTypeId"]').val();

            //修改跟流程ID,流程名称相关的显示(这个修改跟数据json无关,只是前端显示的地方)
            this.__Flowdesigner.updateChgFlowName(data, oldName);

            data.flowlimit['days'] = popWin.find('input[name="limitTime"]').val();
            if (data.flowlimit['days'] == "") {
                data.flowlimit['days'] = 0;
            } else {
                data.flowlimit['days'] = parseInt(data.flowlimit['days']);
                data.flowlimit['type'] = parseInt(popWin.find('select[name="limitType"]').val());
            }

            data.active = parseInt(popWin.find('input[name="active"]:checked').val());
            data.updateToDB = popWin.find('input[name="updateToDB"]').prop('checked');
            data.memo = popWin.find('textarea[name="memo"]').val();

            //表单
            data.forms = {};
            var chgForms = {};
            $.each(this.tblObjArr['tblFlowForm'].rows() || [], function (i, item) {
                if (item) {
                    item.group = popWin.find('input[name="group_' + i + '"]').val();
                    if (item.oldId) {
                        //有旧表单id时,说明系统进行了表单替换
                        chgForms[item.oldId] = item.id;
                        delete item['oldId'];  //删除掉标记值
                    } else {
                        chgForms[item.id] = item.id;
                    }
                    item.sort = i;
                    data.forms[item.id] = item;
                }
            });

            //变量
            data.vars = {};
            $.each(this.tblObjArr['tblFlowVar'].rows() || [], function (i, item) {
                if (item) {
                    data.vars[item.varId] = item;
                }
            });
            //处理因为表单变化带来的影响
            self._chgNodeForDelForm(data.vars, chgForms);
            //表单顺序变化,应用到节点上
            if (self.sortForm) {
                self._sortNodeForm(data.forms);
            }
            //读者
            var reader = {
                authId: 'Reader',
                authName: this.options['participantsName']['Reader'],//'读者',
                person: '',     //个人
                dept: '',       //部门
                group: '',      //群组
                position: '',   //岗位
                msgFlag: ''     //消息类型
            };
            $.each(this.tblObjArr['tblReader'].rows() || [], function (i, item) {
                if (item) {
                    reader[item['type']] += item.data + ';';
                }
            });
            data.participants.Reader = reader;
            //高级
            data.openTodoFlag = popWin.find('select[name="openTodoFlag"]').val();
            data.startRuleClassName = popWin.find('input[name="startRuleClassName"]').val();
            data.checkRoleClassName = popWin.find('input[name="checkRoleClassName"]').val();
            data.trackLogClassName = popWin.find('input[name="trackLogClassName"]').val();
            data.relationRuleClassName = popWin.find('input[name="relationRuleClassName"]').val();

            var title = this._getLang('prop.title')
                .replace('name', data.flowName)
                .replace('id', data.flowId);
            popWin.find('#hzPopModalLabel').html(title);
            return "";
        },
        //对删除替换的表单进行数据处理
        _chgNodeForDelForm: function (vars, chgForms) {
            var self = this;
            if (!self.chgForm) {
                return;
            }
            var fd = this.__Flowdesigner;
            $.each(vars || {}, function (id, obj) {
                if (obj && obj.varFrom != '') {
                    var varFrom = obj.varFrom;
                    var pageId = obj.pageId;
                    var formId = chgForms[pageId];
                    if (formId) { //在现有列表中存在
                        if (formId != varFrom) { //表单被替换了
                            obj.varFrom = varFrom;
                        }
                    } else {
                        //说明表单已经不在列表中被删除掉了,此时删除变量中的varFrom值
                        obj.varFrom = '';
                    }
                }
            })

            $.each(fd.curDrawLayer._nodes || [], function (i, node) {
                if (!node) {
                    return fd.CONTINUE;
                }
                //一共有两个地方涉及到表单,办理人的获取,和表单设置
                $.each(node.participants || [], function (i, participant) {
                    var data = node.data.participants[participant];
                    if (data && data['formField']) {
                        var field = '';
                        $.each(data['formField']['name'].split(';') || [], function (i, value) {
                            if (value) {
                                var ss = value.split('_'); //拆分表单_字段格式
                                var formId = chgForms[ss[0]]; //从现有的表单列表中获取
                                if (formId) {                     //仍然存在
                                    field += formId + '_' + ss[1] + ';';
                                }
                                //不存在的表单的字段被删除掉了
                            }
                        });
                        data['formField']['name'] = field;
                    }
                });

                $.each(node.operators || [], function (i, participant) {
                    var data = node.data.authDo[participant];
                    if (data && data['forms']) {
                        //从现有列表中获取默认表单,如果不存在了则默认FlowTrack
                        var formId = chgForms[data['forms']['dfId']] || 'FlowTrack';
                        data['forms']['dfId'] = formId;

                        var forms = {};
                        $.each(data['forms']['form'] || [], function (key, form) {
                            if (form) {
                                var newId = chgForms[form.id];
                                if (newId) {
                                    //仍然存在时
                                    if (form.id == newId) {
                                        forms[key] = form; //没有变化时
                                    } else {
                                        //表单被替换时
                                        form.id = newId;
                                        form.buttons = ''; //操作和字段权限设置必须清空
                                        if (!(form.fieldControlId == 'allreadonly'
                                            || form.fieldControlId == 'alleditable')) {
                                            form.fieldControlId = participant.indexOf('Author') == -1
                                                ? 'allreadonly' : 'alleditable';
                                        }
                                        forms[newId] = form;
                                    }
                                }
                            }
                        });
                        data['forms']['form'] = forms;
                    }
                });

                node.__drawLayer.data['process'][node.id] = node.data;
            });
        },
        //顺序调整时,对节点表单进行处理
        _sortNodeForm: function (flowForms) {
            var fd = this.__Flowdesigner;
            $.each(fd.curDrawLayer._nodes || [], function (i, node) {
                if (!node) {
                    return fd.CONTINUE;
                }
                $.each(node.operators || [], function (i, participant) {
                    var data = node.data.authDo[participant];
                    if (data && data['forms']) {
                        if (data['forms']['chg'] == 1) {
                            return fd.CONTINUE;        //continue;
                        }
                        var forms = {};
                        var num1 = Object.keys(data['forms']['form'] || []).length;
                        var num2 = 0;
                        var dfId = '';
                        $.each(flowForms, function (id, flowform) {
                            $.each(data['forms']['form'] || [], function (key, form) {
                                if (form) {
                                    if (form.id == flowform.id) {
                                        forms[form.id] = form;
                                        form['sort'] = num2++;

                                        if (dfId == '' && form.id != 'FlowTrack') {
                                            dfId = form.id;
                                        }
                                        return fd.BREAK; //break;
                                    }
                                }
                            });
                            if (num1 == num2) {
                                return fd.BREAK;
                            }
                        });
                        if (data['forms']['dfId'] == 'FlowTrack' && num1 > 1) {
                            data['forms']['dfId'] = dfId;
                        }
                        data['forms']['form'] = forms;
                    }
                });

                node.__drawLayer.data['process'][node.id] = node.data;
            });
        }

    };


    return FlowProperties;
});

define('flowdesigner/element/properties/NodeProperties',['require','jquery','../FlowInit'],function (require) {
    var $ = require('jquery'),
        FlowInit = require('../FlowInit');

    var NodeProperties = function (opts, fd) {
        this.options = opts;
        this.__Flowdesigner = fd;
    };

    NodeProperties.prototype = {
        constructor: NodeProperties,
        tblObjArr: {},
        popHtml: {},
        _getLang: function (key) {
            return this.__Flowdesigner.getLang(key);
        },
        _getHtml: function (key) {
            return this.__Flowdesigner.getHtml(key);
        },
        _showMsg: function (msg, title, callback) {
            this.__Flowdesigner.showMsg(msg, title, callback);
        },
        _chgApplyBtn: function (applyBtn, disabled) {
            this.__Flowdesigner._chgApplyBtn(applyBtn, disabled);
        },
        _initPage: function (node, pos) {
            var navTabs = null;
            var tmpPopHtml = this.popHtml['Type_' + node.nodetype]; //首先从缓存中获取
            if (tmpPopHtml) {
                navTabs = tmpPopHtml.find('#navTabs');
                this._chgOpenHtmlPage(tmpPopHtml, navTabs, node.initProPageNavForSub(), pos);
            } else {
                tmpPopHtml = $(this._getHtml('template/node.html'));
                navTabs = tmpPopHtml.find('#navTabs');
                this._makeHtmlPage(tmpPopHtml, navTabs, node.initProPageNavForSub(), pos);
                this.popHtml['Type_' + node.nodetype] = tmpPopHtml;
            }
            return tmpPopHtml;
        },
        _makeHtmlPage: function (popHtml, navTabs, tabs, pos) {
            var self = this;
            $.each(tabs, function (i, item) {
                var html = '<li role="presentation" ' + (i == pos ? 'class="active"' : '') + '>' +
                    '    <a href="#' + item.id + '" aria-controls="' + item.id +
                    '" role="tab" data-toggle="tab">' + item.name + '</a>' +
                    '</li>';
                if (!item.hide) {
                    navTabs.append(html);
                }

                //对应pos的内容页面激活
                if (i == pos) {
                    popHtml.find('#' + item.id).addClass('active');
                }
                //获取页签对应的页面，继续后续处理
                var pageName = item.id;
                if (item.html) {
                    pageName = item.html;
                }
                var pageHtml = self._getHtml('template/node/' + pageName + '.html');
                //没有下级tbl时，直接加载对应页面
                popHtml.find('#' + item.id).html(pageHtml);

                if (item.page) {
                    //需要替换id值，否则后面的页签不能生效
                    $.each(item.page, function (j, page) {
                        var reg = new RegExp(page, "g"); //创建正则RegExp对象
                        pageHtml = pageHtml.replace(reg, item.id + '_' + page);
                    });
                    popHtml.find('#' + item.id).html(pageHtml);
                    $.each(item.page, function (j, page) {
                        var newId = popHtml.find('#' + item.id + '_' + page);
                        var pageMemo = self._getHtml('template/node/' + pageName + '/' + page + '.html');
                        newId.html(pageMemo);
                    });
                }

                if (item.inner) {
                    $.each(item.inner, function (i, page) {
                        var content = self._getHtml('template/node/' + pageName + '/' + page.html + '.html');
                        popHtml.find('#' + page.id).append(content);
                    });
                }

                if (item.sub) {
                    var nxtNavTabs = popHtml.find('#nav_' + item.id);
                    self._makeHtmlPage(popHtml, nxtNavTabs, item.sub, 0);
                }

            });

        },
        _chgOpenHtmlPage: function (popHtml, navTabs, tabs, pos) {
            var self = this;
            var navs = navTabs.children();

            $.each(tabs, function (i, item) {
                if (i == pos) {
                    $(navs[i]).addClass('active');
                    popHtml.find('#' + item.id).addClass('active');
                } else {
                    $(navs[i]).removeClass('active');
                    popHtml.find('#' + item.id).removeClass('active');
                }
            });
        },
        showProperties: function (node, pos) {
            var self = this;
            var title = this._getLang('prop.title')
                .replace('name', node.data.name)
                .replace('id', node.data.id);
            this.__Flowdesigner.showPopWin({
                title: title,
                popHtml: self._initPage(node, pos),
                data: node,
                width: '1000px',
                height: '435px',
                initFun: function (popWin, node) {
                    return self._initPropertiesData(popWin, node);
                },
                applyFun: function (popWin, node) {
                    return self._applyPropertiesData(popWin, node);
                }
            });
            $('#applyBtn').attr('disabled', true);
        },
        //----------数据初始化-------------------------
        _initPropertiesData: function (popWin, node) {
            this.tblObjArr = {};
            //节点切换下拉框的选项初始化
            this._initChgSelectNodeOptions(popWin, node);
            //基本属性页面
            this._initBase(popWin, node);
            //操作页面放在办理人上面,为了表单内容的加载能在人员页面使用前加载完毕
            this._initOperator(popWin, node);
            //办理人页面
            this._initParticipant(popWin, node);

            //事件页面
            this._initEvent(popWin, node);
            //子流程页面
            this._initSubflow(popWin, node);
            //扩展页面,有基本页面方法一并处理
            // this._initExtendRule(popWin,node);
            //异常页面
            this._initException(popWin, node);
            //节点参数页面
            this._initNodePara(popWin, node);

            // popWin.find('select[name="nodeType"]').change();
            // 不能调用上面的change事件,因为data为空,会造成数据显示的问题,
            // 所以需要显示的调用change的方法并传入data
            node.chgNodeType(popWin, this, node.nodetype, node.data);

            node.initPropertiesData(popWin, this);
            var self = this;
            //示例代码
            popWin.find('.btnExample').on('click', function () {
                self.__Flowdesigner.showExampleJava();
            });
            return "";
        },

        //基本属性页初始化
        _initBase: function (popWin, node) {
            var self = this;
            var data = node.data;
            popWin.find('input[name=nodeId]').val(data.id);
            popWin.find('input[name=nodeName]').val(data.name);

            popWin.find(':radio[name="nxtSelType"][value="' + data['nxtSelType'] + '"]').prop("checked", true);

            //节点类型下拉初始化
            var nodeType = popWin.find('select[name="nodeType"]');
            //selObj, items, labelName, dataName, defVal, tipOption
            this.__Flowdesigner.initSelectOptions(nodeType,
                node.initNodeTypeOption(), null, null, data['nodeType']);
            nodeType.on('change', function () {
                node.chgNodeType(popWin, self, this.value);
            });

            popWin.find('textarea[name="memo"]').val(data['memo']);
        },
        //节点类型下拉框选择项初始化
        _initChgSelectNodeOptions: function (popWin, node) {
            var self = this;
            var allNodes = node.__drawLayer._nodes;
            var selObj = popWin.find('#selectNode');
            //按照节点ID排序输出
            var nodes = self._sortFilterAllNode(allNodes);

            $.each(nodes || [], function (i, data) {
                if (data) {
                    selObj.append('<option value="' + data['id'] + '">' + data['name']
                        + '(' + data['id'] + ')</option>');
                }
            });

            selObj.val(node.id);
            selObj.on('change', function () {
                var nodeid = $(this).val();
                if (nodeid != node.id) {
                    if ($('#applyBtn').attr('disabled')) { //没有修改时,直接切换
                        self._chgSelectNodeOptions(popWin, node, nodeid);
                    } else {
                        //节点被修改时,弹出框,确实是否修改
                        $.confirm({
                            title: self._getLang('static.info'),
                            content: self._getLang('prop.nodechg'),//节点属性已修改,是否保存修改?
                            type: 'blue',
                            icon: 'glyphicon glyphicon-info-sign',
                            backgroundDismiss: false, //是否允许点击背景关闭
                            buttons: {
                                ok: {
                                    text: self._getLang('static.ok'),
                                    btnClass: 'btn-primary',
                                    action: function () {
                                        var msg = self._applyPropertiesData(popWin, node);
                                        if (msg != '') {
                                            self.__Flowdesigner.showMsg(msg);
                                            return;
                                        }
                                        self._chgSelectNodeOptions(popWin, node, nodeid);
                                    }
                                },
                                cancel: {
                                    text: self._getLang('static.cancel'),
                                    btnClass: 'btn-primary',
                                    action: function () {
                                        self._chgSelectNodeOptions(popWin, node, nodeid);
                                    }
                                }
                            }
                        });
                    }
                }
            });
        },
        //对所有节点进行排序
        _sortFilterAllNode: function (allNodes, filterFun) {
            var nodes = [];
            var nodetype = this.options.nodetype['Node_Virtual'];
            $.each(allNodes || [], function (i, data) {
                if (!data) {
                    return true;
                }
                if (data.nodetype == nodetype.data) {
                    return true;
                }
                if (!filterFun || filterFun(data)) {
                    nodes.push({sortNum: data.sortNum, id: data.id, name: data.name});
                }
            });
            nodes.sort(function (a, b) {
                return a.sortNum - b.sortNum;
            });

            return nodes;
        },
        //节点切换时
        _chgSelectNodeOptions: function (popWin, node, nodeid) {
            node.__drawLayer._nodes[nodeid]._showProperties(0);
            /* 如果页签有表格时,会出现一些问题,
            var newNode = node.__drawLayer._nodes[nodeid];
            if(newNode.getStatus() == node.getStatus()){
                var pos = 0;
                var lis = popWin.find('#navTabs').children();
                $.each(lis|| {},function(i,item){
                    if($(item).hasClass('active')){
                        pos = i;
                        return false;
                    }
                });
                newNode._showProperties(pos);
            }
            else{
                newNode._showProperties(0);
            }
            //*/
        },

        //事件初始化
        _initEvent: function (popWin, node) {

            var table = popWin.find('#tblNodeEvent');
            if (table.length == 0) {
                return;
            }
            var self = this;
            self._initCustomClass(self, "customEvent", popWin, false);
            //初始化事件类型下拉框选项
            this.__Flowdesigner.initSelectOptions(
                popWin.find('select[name="eventType"]'), node.getEventTypeArr());

            var items = [];
            $.each(node.data.events || [], function (key, item) {
                if (item) {
                    items.push(item);
                }
            });

            var initData = {
                name: '',
                className: '',
                type: ''
            };
            var tblNodeEvent = table.mmGrid({
                height: 225
                ,delTitle:self._getLang('table.field.defTitle')
                ,showCol:self._getLang('table.field.showCol')
                , cols: this._getNodeEventTableCol(node.getEventTypeArr())
                , items: items      //本地数据

                , multiSelect: false
                , fullWidthRows: true
                , autoLoad: false
                , loadingText: self._getLang('table.event.load')//'正在加载节点事件列表...'
                , noDataText: self._getLang('table.event.nodata')//'请添加节点事件'
            });
            //加载表格
            tblNodeEvent
                .on('cellSelected', function (e, item, rowIndex, colIndex) {
                    //判断当前数据是否被选中
                    var selectIndex = tblNodeEvent.selectedRowsIndex();
                    if (selectIndex[0] == rowIndex) {
                        //取消选中
                        self._initEventSel(popWin, initData);
                        popWin.find('#btnEventAdd').text(self._getLang('prop.add'));//('添加');
                    } else {
                        self._initEventSel(popWin, item);
                        popWin.find('#btnEventAdd').text(self._getLang('prop.apply'));//('应用');
                    }
                })
                .load();
            //记录表格对象,为确认保存数据使用
            this.tblObjArr['tblNodeEvent'] = tblNodeEvent;

            popWin.find('input[name="eventClassName"]').on('dblclick', function () {
                self._dblCkSelEvent(popWin);
            });
            popWin.find('input[name="eventName"]').on('dblclick', function () {
                self._dblCkSelEvent(popWin);
            });

            popWin.find('#btnEventAdd').on('click', function () {
                if (popWin.find('input[name="eventName"]').val() == '') {
                    self._showMsg(self._getLang('table.event.namenull'));//('事件名称不能为空');
                    return;
                }
                if (popWin.find('input[name="eventClassName"]').val() == '') {
                    self._showMsg(self._getLang('table.event.classnull'));//('事件执行类不能为空');
                    return;
                }
                if (!popWin.find('select[name="eventType"]').val()) {
                    self._showMsg(self._getLang('table.event.seltype'));//('请选择事件执行类型');
                    return;
                }
                var selIndex = tblNodeEvent.selectedRowsIndex();
                var allRows = tblNodeEvent.rows();
                if (selIndex.length == 1) {
                    var selItem = tblNodeEvent.selectedRows();
                    var oldId = selItem[0]['type'];
                    var item = self._makeEventItem(popWin, allRows, oldId);
                    if (item == null) {
                        self._showMsg(self._getLang('table.event.chgtypeExist'));//('修改后的事件类型已经存在,每种类型只能添加一次');
                        return;
                    }
                    tblNodeEvent.updateRow(item, selIndex[0]);
                } else {
                    var item = self._makeEventItem(popWin, allRows, null);
                    if (item == null) {
                        self._showMsg(self._getLang('table.event.typeExist'));//('事件类型已经存在');
                        return;
                    }
                    tblNodeEvent.addRow(item);
                    tblNodeEvent.select(tblNodeEvent.rowsLength() - 1);
                    popWin.find('#btnEventAdd').text(self._getLang('prop.apply'));//('应用');
                }
                self._chgApplyBtn(popWin.find('#applyBtn'), false);
            });
            popWin.find('#btnEventDel').on('click', function () {
                if (self.__Flowdesigner.delCheckSel(tblNodeEvent)) {
                    return;
                }
                self.__Flowdesigner.applyQuestion(self._getLang('table.event.del'), function () {
                    tblNodeEvent.removeRow(tblNodeEvent.selectedRowsIndex());
                    self._initEventSel(popWin, initData);
                    self._chgApplyBtn(popWin.find('#applyBtn'), false);
                });
            });
            popWin.find('#btnEventDelAll').on('click', function () {
                self.__Flowdesigner.applyQuestion(self._getLang('table.event.delAll'), function () {
                    tblNodeEvent.removeRow();
                    self._initEventSel(popWin, initData);
                    self._chgApplyBtn(popWin.find('#applyBtn'), false);
                });
            });
            popWin.find('button[name="btnCustonEventAdd"]').on('click', function () {
                self.addCustomClass($(this), "customEvent");
            });
            popWin.find('button[name="btnCustonEventDel"]').on('click', function () {
                var customEventSelectEle = $(this).parents("tbody").find("select[name='customEventSelect']");
                self.delCustomClass("customEvent", customEventSelectEle);
            });
            popWin.find("select[name='customEventSelect']").on('change', function () {
                var $this = $(this);
                $this.parents('.chgPanel-group').find("input[name='eventId']").val($this.val());
                $this.parents('.chgPanel-group').find("input[name='eventName']").val($this.find("option:selected").attr("event-name"));
                $this.parents('.chgPanel-group').find("input[name='eventClassName']").val($this.find("option:selected").attr("event-class"));
                self._chgApplyBtn(popWin.find('#applyBtn'), false);
            });
        },
        _makeEventItem: function (popWin, allItem, ignoreId) {
            var isHave = false;
            var newId = popWin.find('select[name="eventType"]').val();
            $.each(allItem || [], function (i, item) {
                if (item && item['type'] != ignoreId && item['type'] == newId) {
                    isHave = true;
                    return false;
                }
            });
            if (isHave) {
                return null;
            }
            var item = {};
            item['type'] = newId;
            item['name'] = popWin.find('input[name="eventName"]').val();
            item['className'] = popWin.find('input[name="eventClassName"]').val();

            return item;
        },
        _initEventSel: function (popWin, item) {
            //取消选中
            popWin.find('input[name="eventName"]').val(item['name']);
            popWin.find('input[name="eventClassName"]').val(item['className']);
            popWin.find('select[name="eventType"]').val(item['type']);
            popWin.find('select[name="customEventSelect"]').find('option').prop("selected", false);
            if (item['className']) {
                popWin.find('select[name="customEventSelect"]').find('option[event-class="' + item['className'] + '"]').prop("selected", true);
            } else {
                $(popWin.find('select[name="customEventSelect"]').find('option')[0]).prop("selected", true);
            }

        },
        _getNodeEventTableCol: function (typeArr) {
            var self = this;
            var title = self._getLang('table.event.title');
            return [
                {
                    title: title[0],//'事件名称',
                    name: 'name',
                    width: 270,
                    lockWidth: true
                },
                {
                    title: title[1],//'事件处理类',
                    name: 'className',
                    width: 500
                },
                {
                    title: title[2],//'事件类型',
                    name: 'type',
                    width: 180,
                    lockWidth: true,
                    renderer: function (val, item, rowIndex) {
                        return self.__Flowdesigner.getLabelFromList(typeArr, val);
                    }
                }
            ];
        },
        _dblCkSelEvent: function (popWin) {
            var self = this;
            this.__Flowdesigner.openWinForSelEvent(function (name, clazz) {
                popWin.find('input[name="eventName"]').val(name);
                popWin.find('input[name="eventClassName"]').val(clazz);
                self._chgApplyBtn(popWin.find('#applyBtn'), false);
            });
        },
        //办理人初始化
        _initParticipant: function (popWin, node) {
            var self = this;
            $.each(node.participants || [], function (i, participant) {
                if (!participant) {
                    return true;
                }
                self._initUserProperties(popWin, participant, node);
                self._initUserOrg(popWin, participant, node);
                self._initUserField(popWin, participant, node);
                self._initUserVar(popWin, participant, node);
                self._initUserRelation(popWin, participant, node);
                self._initUserRule(popWin, participant, node);
                self._initUserCustomer(popWin, participant, node);
            });
        },
        _initUserProperties: function (popWin, participant, node) {
            var self = this;
            var data = node.data.participants[participant];//可能为undefined
            var sendMsgHtml = self._getLang('prop.msgflag') + '<br>';
            if (!data) {
                var defMsgSel = self.options['defSendMsg'] || '';
                data = {
                    msgFlag: defMsgSel,
                    control: 'FreeSelect;AgentFlag',
                    passNode: ''
                };
            }
            var msgFlag = data['msgFlag'];
            if (!msgFlag) {
                msgFlag = '';
            }
            $.each(this.options.sendMsg, function (key, label) {
                if (key != 'Read') {
                    sendMsgHtml += '<label class="checkbox-inline">' +
                        '<input type="checkbox" class="checkChange" name="sendMsg"' +
                        ' value="' + key + '" ' + (msgFlag.indexOf(key) != -1 ? 'checked' : '') + ' />' + label +
                        '</label><br>';
                }
            });
            popWin.find('#p' + participant + '_sendMsg').html(sendMsgHtml);
            // popWin.find('#p'+key+'_sendMsg').find('input[name="sendMsg"]').on('change')
            var controlConfig = this.options.control;
            var controlHtml = self._getLang('prop.propset') + '<BR>';
            var controlData = data['control'];
            var hasPassNode = false;
            var hasFreeSelect = false;
            $.each(controlConfig[participant], function (i, key) {
                var checked = controlData.indexOf(key) != -1;
                var control = controlConfig[key];
                controlHtml += '<label class="checkbox-inline" ' +
                    (control['title'] ? (' title="' + control['title'] + '"') : '')
                    + '>' +
                    '<input type="checkbox" class="checkChange" name="control"' +
                    ' value="' + key + '" ' + (checked ? 'checked' : '') + ' />' +
                    control['label'] +
                    '</label><br>';
                if (control['passNode']) {
                    hasPassNode = true;
                    var label = '';
                    if (data['passNode'] && node.__drawLayer._nodes[data['passNode']]) {
                        label = node.__drawLayer._nodes[data['passNode']].name + '(' + data['passNode'] + ')';
                    }
                    //跳过节点显示
                    controlHtml += '<p style="margin-bottom: 0px;margin-left: 20px;display:' + (checked ? '' : 'none')
                        + '">' + self._getLang('prop.selnode') + '<br><input type="text" name="passNode" data="' +
                        data['passNode'] + '"  value="' + label + '" readonly style="width:100%;height: 27px;"></p>'
                }
                if (control['select']) {
                    hasFreeSelect = true;
                    var selectArea = data['select'] || '';
                    //自由选择范围显示
                    controlHtml += '<p style="margin-bottom: 0px;margin-left: 20px;display:' + (checked ? '' : 'none')
                        + '">';
                    $.each(control['area'], function (i, item) {
                        controlHtml += '<label class="checkbox-inline" style="' +
                            ' margin-left: 0px;margin-right: 10px;">';
                        controlHtml += '<input type="checkbox" class="checkChange" name="selectArea" ' +
                            'value="' + item.data + '"' + (selectArea.indexOf(item.data) == -1 ? '' : 'checked') + '/>' +
                            item.label;
                        controlHtml += '</label>';
                    });
                    controlHtml += '</p>';
                }
            });
            var control = popWin.find('#p' + participant + '_control');
            control.html(controlHtml);
            if (hasPassNode) {
                var passNode = control.find('input[name="passNode"]');
                var passNodeUser = control.find('input[name="control"][value="PassNodeUser"]');
                passNodeUser.on('change', function () {
                    if (this.checked) {
                        passNode.parent().show();
                    } else {
                        passNode.parent().hide();
                    }
                });
                passNode.on('click', function () {
                    self._selectNodeAndBack(node,
                        function (data) {
                            if (data && data.length > 0) {//有可能是一个也不选择,想清空的情况
                                passNode.val(data[0].label);
                                passNode.attr('data', data[0].data);
                            } else {
                                passNode.val('');
                                passNode.attr('data', '');
                            }
                            self._chgApplyBtn($('#applyBtn'), false);
                        }, false, passNode.attr('data') + ';',
                        function (item) {
                            if (item.id == node.id) {
                                return false; //不能选择自己
                            }
                            return true;
                        }
                    );
                });
            }
            if (hasFreeSelect) {
                var freeSelect = control.find('input[name="control"][value="FreeSelect"]');
                freeSelect.on('change', function () {
                    if (this.checked) {
                        $(this).parent().next().next().show();
                    } else {
                        $(this).parent().next().next().hide();
                    }
                });
            }
        },
        _initUserOrg: function (popWin, key, node) {
            var data = node.data.participants[key];//可能为undefined
            var self = this;
            var userOrgKey = key + '_userOrg';
            var userOrg = popWin.find('#p' + userOrgKey);
            //在多人并行节点时,需要从Author的table中获取数据,所以必须同步获取才行
            var async = key != 'Author'
                || node.nodetype != this.options.nodetype.Node_Multi.data
                || !(node.data.special &&
                    (node.data.special['passType'] == 2 || node.data.special['passType'] == 3));
            this.__Flowdesigner.initOrgData(data, userOrg, this.tblObjArr, userOrgKey, 240, async);
        },


        delCustomClass: function (type, selectEle) {
            var self = this;
            if (selectEle.val()) {
                self.__Flowdesigner.applyQuestion(self.__Flowdesigner.getLang('html.node.user.del'), function () {
                    self.__Flowdesigner._delCustomClass(selectEle.val(), function () {
                        self._initCustomClass(self, type, selectEle.parent(), false);
                    });
                });
            } else {
                self.__Flowdesigner.showMsg(self.getLang('html.node.user.delcksel'));
            }
        },
        addCustomClass: function ($this, type) {
            var self = this.__Flowdesigner;
            var html = "<div>" +
                "<div style='height: 30px; padding-top: 10px;'>" +
                self.getLang('html.node.user.customClassname') +
                "：</div> <input style='width: 100%' type='text' maxlength='100' onkeyup='this.value=this.value.replace(/\\s+/g,\"\")' name='customClassName' placeholder='" + self.getLang('html.node.user.pleaseinput') + "'/>" +
                "</div><div>" +
                "<div style=' padding-top: 10px;'>" +
                self.getLang('html.node.user.customClass') +
                ": </div> <input style='width: 100%' type='text' maxlength='200' onkeyup='this.value=this.value.replace(/\\s+/g,\"\")' name='customClassPath' placeholder='" + self.getLang('html.node.user.pleaseinput') + "'/>" +
                "</div>";
            self.popSelWin(self.getLang('html.node.' + type), html,
                function ($content) {
                    if (!$content.find("input[name='customClassName']").val() || !$content.find("input[name='customClassPath']").val()) {
                        self.showMsg(self.getLang('msg.isNull.customClazz'));
                        return false;
                    }
                    var para = {
                        "clsName": $content.find("input[name='customClassName']").val(),
                        "cls": $content.find("input[name='customClassPath']").val(),
                        "type": type
                    }
                    self._addCustomClass(para, function (result) {
                        var eleName = "customClassSelect";
                        var ele = $this.parent().find("select[name='" + eleName + "']");
                        var option = "<option user-class='" + result.cls + "' value='" + result.id + "'>" + result.clsName + "(" + result.cls + ")</option>"
                        if (type == "customEvent") {
                            eleName = "customEventSelect";
                            ele = $this.parents("tbody").find("select[name='" + eleName + "']");
                            option = "<option event-name='" + result.clsName + "' event-class='" + result.cls + "' value='" + result.id + "'>" + result.clsName + "(" + result.cls + ")</option>"
                        }
                        ele.append(option);
                        ele.find("option[value='" + result.id + "']").attr("selected", true);
                        ele.trigger("change");
                    })
                }, "400px", self.getLang('static.save'), null, true)
        },

        tmpFormName: {},//用来临时存放当前节点选中的节点列表的中文名称
        _initUserFiledSel: function (popWin, key, forms) {
            var self = this;
            var userFieldKey = key + '_userField';
            var userField = popWin.find('#p' + userFieldKey);
            if (!userField.html()) {
                return;
            }
            // console.log(userField.html());
            //初始化下拉框
            var selFormObj = userField.find('select[name="userForm"]');
            var selFieldObj = userField.find('select[name="userField"]');

            this._initUserFieldOption(selFormObj, selFieldObj, forms);
        },
        _initUserFieldOption: function (selFormObj, selFieldObj, forms) {
            var self = this;
            selFieldObj.empty();
            selFormObj.empty();
            selFormObj.append('<option value="">' + self._getLang('prop.selform') + '</option>');//请指定表单

            $.each(forms || [], function (key, item) {
                if (item && key != 'FlowTrack') {
                    if (item.name) {
                        self.tmpFormName[key] = item.name;
                    }
                    selFormObj.append('<option value="' + key + '" data="' + item.type + '">' + item.name + '</option>');
                }
            });
        },
        _initUserField: function (popWin, key, node) {
            var data = node.data.participants[key];//可能为undefined
            if (!data) {
                data = {
                    formField: {        //从字段中获取
                        union: '2',     //默认并集处理,解析部分暂时不支持交集处理,所以此处只能为2
                        name: '',       //对应的字段名称
                        pageId: ''      //所属的表单ID
                    }
                };
            }
            var self = this;
            var userFieldKey = key + '_userField';
            var userField = popWin.find('#p' + userFieldKey);
            //初始化下拉框
            var selFormObj = userField.find('select[name="userForm"]');
            var selFieldObj = userField.find('select[name="userField"]');

            //20200929 LIYS 此处不需要加载表单列表,在操作表单加载时已经加载过了,
            //此时的forms中对象没有name属性值,如果加载会没有中文显示
            //var forms = node.data.authDo[key]['forms']['form'];
            //this._initUserFieldOption(selFormObj,selFieldObj,forms);

            selFormObj.on('change', function () {
                self.__Flowdesigner.initFieldSelect(selFieldObj, this.value);
            });
            var allFields = data['formField']['name'];
            var pageIds = data['formField']['pageId'];
            var items = [];
            if (allFields) {
                $.each(allFields.split(";") || [], function (i, field) {
                    if (field) {
                        items.push({
                            data: field,
                            pageId: typeof (pageIds) != "undefined" ? pageIds.split(";")[i] : ""
                        })
                    }
                });
            }

            var tblUserField = userField.find('#tblUserField').mmGrid({
                height: 125
                ,delTitle:self._getLang('table.field.defTitle')
                ,showCol:self._getLang('table.field.showCol')
                , cols: this._getUserFieldTableCol()
                , items: items      //本地数据

                , multiSelect: false
                , fullWidthRows: true
                , autoLoad: false
                , loadingText: self._getLang('table.field.load')//'正在加载字段列表...'
                , noDataText: self._getLang('table.field.nodata')//'请添加字段'
            });
            tblUserField
                .on('cellSelected', function (e, item, rowIndex, colIndex) {
                    //判断当前数据是否被选中
                    var selectIndex = tblUserField.selectedRowsIndex();
                    if (selectIndex[0] == rowIndex) {
                        //取消选中
                        selFormObj.val('');
                        selFieldObj.empty();
                    } else {
                        selFormObj.val(item.pageId);
                        selFormObj.change();
                        var fieldId = item.data;
                        if (selFormObj.find('option[value="' + fieldId + '"]').length == 0) {
                            fieldId = item.pageId + '_' + fieldId.substring(fieldId.indexOf('_') + 1, fieldId.length);
                        }
                        selFieldObj.val(fieldId);
                    }
                })
                .load();
            this.tblObjArr[userFieldKey] = tblUserField;
            userField.find('#btnFieldAdd').on('click', function () {
                if (selFieldObj.val()) {
                    var selIndex = tblUserField.selectedRowsIndex();
                    var allRows = tblUserField.rows();
                    var newId = selFieldObj.val();
                    if (selIndex.length == 1) {
                        var selItem = tblUserField.selectedRows();
                        var oldId = selItem[0]['data'];

                        if (oldId == newId) {
                            return;//未修改
                        }
                        var isHave = self._checkField(allRows, newId);
                        if (isHave) {
                            self._showMsg(self._getLang('table.field.chgexist'));//('修改后的字段已经存在');
                            return;
                        }
                        tblUserField.updateRow({data: newId, pageId: selFormObj.val()}, selIndex[0]);
                    } else {
                        var isHave = self._checkField(allRows, newId);
                        if (isHave) {
                            self._showMsg(self._getLang('table.field.exist'));//('字段已经存在');
                            return;
                        }
                        tblUserField.addRow({data: newId, pageId: selFormObj.val()});
                    }
                    self._chgApplyBtn(popWin.find('#applyBtn'), false);
                } else {
                    self._showMsg(self._getLang('prop.selfield'));//('请选择字段');
                }
            });
            userField.find('#btnFieldDel').on('click', function () {
                if (self.__Flowdesigner.delCheckSel(tblUserField)) {
                    return;
                }
                self.__Flowdesigner.applyQuestion(self._getLang('table.field.del'), function () {
                    tblUserField.removeRow(tblUserField.selectedRowsIndex());
                    self._chgApplyBtn(popWin.find('#applyBtn'), false);
                });
            });
            userField.find('#btnFieldDelAll').on('click', function () {
                self.__Flowdesigner.applyQuestion(self._getLang('table.field.delAll'), function () {
                    tblUserField.removeRow();
                    self._chgApplyBtn(popWin.find('#applyBtn'), false);
                });
            });
        },

        _checkField: function (allRows, newId) {
            var isHave = false;
            $.each(allRows || [], function (i, item) {
                if (item && item.data == newId) {
                    isHave = true;
                    return false;
                }
            });
            return isHave;
        },
        _getUserFieldTableCol: function () {
            var self = this;
            var formInfo = self.__Flowdesigner.curDrawLayer.forms;
            return [
                {
                    title: self._getLang('table.field.title')[0],
                    name: 'data',
                    width: 605,
                    sortable: true,
                    align: 'left',
                    renderer: function (val, item, rowsIndex) {
                        //20200929 LIYS js中的split会拆分成数组,
                        //var ff = val.split("_");
                        var pageId = item.pageId;
                        if (pageId != "") {
                            var fields = formInfo[pageId] ? formInfo[pageId]['fields'] : [];
                            var field = fields['mixed_' + val];//替换表单后可能字段不存在了
                            if (!field) {
                                field = fields[val];
                            }
                            if (!field) {
                                field = fields['mixed_' + pageId + '_' + val.substring(val.indexOf('_') + 1, val.length)];
                            }
                            if (field && field.indexOf("&")) {
                                field = field.split("&")[1];
                            }
                            if (!field) {
                                return self.tmpFormName[pageId] + "_" + val + "(<span style='color:red'>"+self._getLang('html.node.user.notFound')+"</span>)";
                            }
                        } else {
                            var pos = val.indexOf('_');
                            pageId = val.substring(0, pos);
                            var fieldName = val.substring(pos + 1);
                            var fields = formInfo[pageId]['fields'];
                            var field = fields[fieldName] || fieldName;//替换表单后可能字段不存在了
                        }
                        return self.tmpFormName[pageId] + "_" + field;
                    }
                }
            ];
        },
        _initUserVar: function (popWin, key, node) {
            var data = node.data.participants[key];
            if (!data) {
                data = {
                    flowVar: {          //从流程变量中获取
                        union: '2',     //默认并集处理,解析部分暂时不支持交集处理,所以此处只能为2
                        name: ''        //变量id
                    }
                };
            }
            var self = this;
            var userVarKey = key + '_userVar';
            var userVar = popWin.find('#p' + userVarKey);
            var vars = node.__drawLayer.data.flowInfo['vars'];
            var items = [];
            var selVars = data.flowVar['name'].split(';');
            $.each(vars || [], function (i, item) {
                if (item && item.varType == 6) {
                    if (self._ckTableRowSelect(selVars, item)) {
                        item.sel = true;
                    } else {
                        item.sel = false;
                    }
                    items.push(item);
                }
            });
            var tblUserVar = userVar.find('#tblUserVar').mmGrid({
                height: 113
                ,delTitle:self._getLang('table.field.defTitle')
                ,showCol:self._getLang('table.field.showCol')
                , cols: this._getUserVarTableCol()
                , items: items      //本地数据
                // , checkCol:true
                , multiSelect: false
                , fullWidthRows: true
                , autoLoad: false
                , loadingText: self._getLang('table.uservar.load')//'正在加载变量列表...'
                , noDataText: self._getLang('table.uservar.nodata')//'当前无可选变量'
            });
            tblUserVar
                .on('cellSelected', function (e, item, rowIndex, colIndex) {
                    item.sel = !item.sel;
                    tblUserVar.load(tblUserVar);
                    self._chgApplyBtn(popWin.find('#applyBtn'), false);
                })
                .load();

            this.tblObjArr[userVarKey] = tblUserVar;


        },
        _ckTableRowSelect: function (selVars, item) {
            var ck = false;
            $.each(selVars || [], function (i, varid) {
                if (varid && item.varId == varid) {
                    ck = true;
                    return false;
                }
            });
            return ck;
        },
        _getUserVarTableCol: function () {
            var self = this;
            var title = self._getLang('table.uservar.title');
            return [
                {
                    title: title[0],//'选择',
                    name: 'sel',
                    width: 50,
                    align: 'center',
                    lockWidth: true,
                    renderer: function (val, item, rowIndex) {
                        return '<div class="' + (val ? 'tableRowSelect' : 'tableRowNoSelect') + '"></div>';
                    }
                },
                {
                    title: title[1],// '变量ID',
                    name: 'varId',
                    width: 190,
                    align: 'left'
                },
                {
                    title: title[2],// '变量名称',
                    name: 'varName',
                    width: 200,
                    align: 'left'
                },
                {
                    title: title[3],//'变量类型',
                    name: 'varType',
                    width: 170,
                    align: 'left',
                    renderer: function (val, item, rowIndex) {
                        return self.__Flowdesigner.getLabelFromList(self.options.varTypes, val);
                    }
                }
            ];
        },

        _initUserRelation: function (popWin, key, node) {
            var data = node.data.participants[key];
            if (!data) {
                data = {
                    relation: [
                        // 按关系获取,可以是多个
                        //根据initRelation获取一个新的关系对象
                    ]
                };
            }
            var self = this;
            var userRelationKey = key + '_userRelation';
            var userRelation = popWin.find('#p' + userRelationKey);
            var items = data['relation'];

            //初始化下拉框
            var nodeSel = userRelation.find('select[name="rNode"]');
            var rNode = userRelation.find('input[name="rNode"]');
            var baseSel = userRelation.find('select[name="rBase"]');
            var relationSel = userRelation.find('select[name="relation"]');
            var relations = this.options.relations;//配置信息
            //用于表格显示时,转换为中文
            var nodeOption = this.options.relationNodeOption;//{d_0:'无',d_1:'上一节点',d_2:'指定节点'};
            var baseOption = this.options.relationBaseOption;//{d_0:'无',d_1:'办理人',d_2:'流程启动者',d_3:'当前执行人'};
            var relationOption = this.options.relationOption;// {d_Creator:'流程启动者',d_PreDone:'上一节点办理',d_CurUser:'当前执行人'};
            $.each(relations, function (i, item) {
                relationOption['d_' + item.data] = item.label;
            });

            //相对节点下拉框
            $.each(nodeOption, function (key, value) {
                var data = key.split('_')[1];
                nodeSel.append('<option value="' + data + '">' + value + '</option>');
            });

            nodeSel.on('change', function () {
                //相对节点变化时,相对基准需要重置,相对关系也需要重置
                baseSel.empty();
                if (this.value == '0') {//相对节点为"无"时
                    $.each(baseOption, function (key, value) {
                        var data = key.split('_')[1];
                        if (data != '1') {
                            baseSel.append('<option value="' + data + '">' + value + '</option>');
                        }
                    });
                } else {//相对节点不为"无"时
                    baseSel.append('<option value="1">' + self._getLang('prop.relation.user') + '</option>');
                }

                if (this.value == '2') {
                    rNode.show();
                } else {
                    rNode.hide();
                }
                //执行一次相对基准的变化,以便相对关系变化
                baseSel.change();
            });
            baseSel.on('change', function () {
                relationSel.empty();
                if (this.value == '0') {
                    relationSel.append('<option value="Creator">' + self._getLang('prop.relation.creator') + '</option>');
                    relationSel.append('<option value="PreDone">' + self._getLang('prop.relation.preuser') + '</option>');
                    relationSel.append('<option value="CurUser">' + self._getLang('prop.relation.curuser') + '</option>');
                } else {
                    $.each(relations, function (i, item) {
                        relationSel.append('<option value="' + item.data + '">' + item.label + '</option>');
                    });
                }
            });
            nodeSel.change();
            baseSel.change();

            rNode.on('click', function () {
                self._selectNodeAndBack(node,
                    // {selStartNode:false,selEndNode:false,isContainsMe:true},
                    function (data) {
                        if (data && data.length > 0) {//有可能是一个也不选择,想清空的情况
                            rNode.val(data[0].label);
                            rNode.attr('data', data[0].data);
                        } else {
                            rNode.val('');
                            rNode.attr('data', '');
                        }
                    }, false, rNode.attr('data') + ';');
            });
            var tblUserRelation = userRelation.find('#tblUserRelation').mmGrid({
                height: 95
                ,delTitle:self._getLang('table.field.defTitle')
                ,showCol:self._getLang('table.field.showCol')
                , cols: this._getUserRelationTableCol(nodeOption, baseOption, relationOption)
                , items: items      //本地数据
                , multiSelect: true
                , fullWidthRows: true
                , autoLoad: false
                , loadingText: self._getLang('table.relation.load')//'正在加载相对关系列表...'
                , noDataText: self._getLang('table.relation.nodata')//'请添加相对关系'
            });
            tblUserRelation.load();

            this.tblObjArr[userRelationKey] = tblUserRelation;

            //初始化按钮
            userRelation.find('#btnRelationAdd').on('click', function () {
                var allRows = tblUserRelation.rows();
                var node = nodeSel.val(),
                    base = baseSel.val(),
                    relation = relationSel.val();

                var rNode = userRelation.find('input[name="rNode"]').attr('data');
                if (node == '2') {
                    node = rNode;
                }
                if (!node || node == '') {
                    self._showMsg(self._getLang('prop.selnode'));//('请指定节点');
                    return;
                }
                var isHave = false;
                $.each(allRows || [], function (i, item) {
                    if (item && item.node == node &&
                        item.base == base && item.relation == relation) {
                        isHave = true;
                        return false;
                    }
                });
                if (isHave) {
                    self._showMsg(self._getLang('table.relation.exist'));//('关系已经存在,请勿重复添加.');
                    return;
                }
                tblUserRelation.addRow({
                    base: base,
                    node: node,
                    relation: relation,
                    union: '2'
                });
                self._chgApplyBtn(popWin.find('#applyBtn'), false);
            })
            userRelation.find('#btnRelationDel').on('click', function () {
                if (self.__Flowdesigner.delCheckSel(tblUserRelation)) {
                    return;
                }
                self.__Flowdesigner.applyQuestion(self._getLang('table.relation.del'), function () {
                    tblUserRelation.removeRow(tblUserRelation.selectedRowsIndex());
                    self._chgApplyBtn(popWin.find('#applyBtn'), false);
                });
            });
            userRelation.find('#btnRelationDelAll').on('click', function () {
                self.__Flowdesigner.applyQuestion(self._getLang('table.relation.delAll'), function () {
                    tblUserRelation.removeRow();
                    self._chgApplyBtn(popWin.find('#applyBtn'), false);
                });
            });

        },
        _getUserRelationTableCol: function (nodeOption, baseOption, relationOption) {
            var nodeName = {};
            $.each(this.__Flowdesigner.curDrawLayer._nodes || [], function (i, node) {
                if (node) {
                    nodeName[node.id] = node.name;
                }
            });
            var title = this._getLang('table.relation.title');
            return [
                {
                    title: title[0],//'相对节点',
                    name: 'node',
                    width: 170,
                    align: 'left',
                    renderer: function (val, item, rowIndex) {
                        if (val == '0' || val == '1') {
                            return nodeOption['d_' + val];
                        } else {
                            return nodeName[val] + '(' + val + ')';
                        }
                    }
                },
                {
                    title: title[1],//'相对基准',
                    name: 'base',
                    width: 160,
                    align: 'left',
                    renderer: function (val, item, rowIndex) {
                        return baseOption['d_' + val];
                    }
                },
                {
                    title: title[2],//'相对关系',
                    name: 'relation',
                    width: 280,
                    align: 'left',
                    renderer: function (val, item, rowIndex) {
                        return relationOption['d_' + val];
                    }
                }
            ];
        },

        _initUserRule: function (popWin, key, node) {
            var data = node.data.participants[key];//可能为undefined
            if (!data) {
                data = {
                    rule: {             //根据规则获取
                        id: '',         //规则对应的数据id
                        text: '',       //规则显示的文本内容
                        script: ''      //规则可以执行的脚本内容
                    }
                };
            }
            var self = this;
            var userRuleKey = key + '_userRule';
            var userRule = popWin.find('#p' + userRuleKey);

            this.__Flowdesigner.onlyBindRule(node, userRule, 'user', data['rule'], false, 'Org');
        },
        customClass: {
            "customUser": [],
            "customEvent": []
        },
        _initUserCustomer: function (popWin, key, node) {
            var data = node.data.participants[key];//可能为undefined
            if (!data) {
                data = {
                    customer: {          //自定义
                        className: '',   //解析memo内容的实现类
                        memo: '',       //自定义内容
                        check: 0        //是否启用0=不启用,1=启用并忽略其他设置
                    }
                };
            }
            var self = this;
            var userCustomerKey = key + '_userCustomer';
            var userCustomer = popWin.find('#p' + userCustomerKey);
            userCustomer.find('input[name="customerCheck"]').prop('checked', data['customer']['check']);
            userCustomer.find('textarea[name="customerMemo"]').val(data['customer']['memo']);
            self._initCustomClass(self, "customUser", userCustomer, true, data);
            userCustomer.find('button[name="addUserCustomClassBtn"]').on('click', function () {
                self.addCustomClass($(this), "customUser");
            });
            userCustomer.find('button[name="delUserCustomClassBtn"]').on('click', function () {
                var customClassSelectEle = $(this).parent().find("select[name='customClassSelect']");
                self.delCustomClass("customUser", customClassSelectEle);
            });
            userCustomer.find("select[name='customClassSelect']").on('change', function () {
                var $this = $(this);
                $this.parent().find(".customerClass").val($this.find("option:selected").attr("user-class"));
                self._chgApplyBtn(popWin.find('#applyBtn'), false);
            });
        },
        _initCustomClass: function (self, type, content, isCache, selectItem) {
            var customClassSelectEle = null;
            if (type == 'customUser') {
                customClassSelectEle = content.find("select[name='customClassSelect']");
                if (selectItem) {
                    content.find('.customerClass').val(selectItem['customer']['className']);
                }
            } else {
                customClassSelectEle = content.find("select[name='customEventSelect']");
            }
            if (self.customClass[type].length > 0 && isCache) {
                self._initCustomClassEle(self, self.customClass[type], customClassSelectEle, type, selectItem);
            } else {
                self.__Flowdesigner._getCustomClassByType(type, function (data) {
                    self.customClass[type] = data;
                    self._initCustomClassEle(self, data, customClassSelectEle, type, selectItem);
                });
            }
        },
        _initCustomClassEle: function (self, data, content, type, selectItem) {
            var option = "<option value=''>" + self._getLang('html.node.user.pleaseSelect') + "</option>";
            for (var i = 0; i < data.length; i++) {
                var item = data[i];
                var selected = "";
                if (selectItem && item.id == selectItem['customer']['classId']) {
                    selected = "selected";
                    content.find('.customerClass').val(selectItem['customer']['customClass']);
                }
                if (type == 'customUser') {
                    option += "<option user-class='" + item.cls + "' value='" + item.id + "'" + selected + ">" + item.clsName + "(" + item.cls + ")</option>"

                } else {
                    option += "<option event-name='" + item.clsName + "' event-class='" + item.cls + "' value='" + item.id + "'" + selected + ">" + item.clsName + "(" + item.cls + ")</option>"
                }
            }
            content.html(option);
        },
        //子流程初始化
        _initSubflow: function (popWin, node) {
            var table = popWin.find('#tblNodeSubflow');
            if (table.length == 0) {
                return;
            }
            var self = this;
            //初始化主流程变量的下拉框,这个不变
            var mainVars = node.initVar_MsgPara();
            this.__Flowdesigner.initSelectOptions(
                popWin.find('select[name="mainVar"]'), mainVars);

            var items = [];
            if (node.data.subflow) {
                popWin.find('input[name="wait"]').prop('checked', node.data.subflow['wait']);
                var mm = popWin.find('input[name="multi"]');
                mm.prop('checked', node.data.subflow['multi']);
                //20200716 LIYS 增加限制,子流程节点只允许选择一个子流程则不能启动多个
                if (node.nodetype == '60') {
                    mm.prop('checked', false);
                    mm.attr('disabled', true);
                }

                $.each(node.data.subflow['flows'] || [], function (i, item) {
                    if (item) {
                        items.push(item);
                    }
                });
            }
            var tblNodeSubflow = table.mmGrid({
                height: 115
                ,delTitle:self._getLang('table.field.defTitle')
                ,showCol:self._getLang('table.field.showCol')
                , cols: this._getNodeSubflowTableCol()
                , items: items      //本地数据

                , multiSelect: false
                , fullWidthRows: true
                , autoLoad: false
                , loadingText: self._getLang('table.subflow.load')//'正在加载子流程列表...'
                , noDataText: self._getLang('table.subflow.nodata')//'请添加子流程'
            });
            //加载表格
            tblNodeSubflow
                .on('cellSelected', function (e, item, rowIndex, colIndex) {
                    //判断当前数据是否被选中
                    var selectIndex = tblNodeSubflow.selectedRowsIndex();
                    if (selectIndex[0] == rowIndex) {
                        //取消选中
                        self._initSubflowSel(popWin, null);
                        popWin.find('#btnSubParaAdd').prop('disabled', true);
                    } else {
                        self._initSubflowSel(popWin, item);
                        popWin.find('#btnSubParaAdd').prop('disabled', false);
                    }
                })
                .load();
            //记录表格对象,为确认保存数据使用
            this.tblObjArr['tblNodeSubflow'] = tblNodeSubflow;
            //按钮事件绑定
            popWin.find('#btnSubflowAdd').on('click', function () {
                var rows = tblNodeSubflow.rows();
                var isRow = rows[0] ? true : false;

                if (!popWin.find('input[name="multi"]').prop('checked') && isRow) {
                    self._showMsg(self._getLang('table.subflow.sel'));//('不允许启动多个子流程时,不能选择多个子流程');

                } else {
                    self._selectSubflow(tblNodeSubflow);
                }
            });
            popWin.find('#btnSubflowDel').on('click', function () {
                if (self.__Flowdesigner.delCheckSel(tblNodeSubflow)) {
                    return;
                }
                self.__Flowdesigner.applyQuestion(self._getLang('table.subflow.del'), function () {
                    tblNodeSubflow.removeRow(tblNodeSubflow.selectedRowsIndex());
                    self._initSubflowSel(popWin, null);
                    self._chgApplyBtn(popWin.find('#applyBtn'), false);
                });
            });
            popWin.find('#btnSubflowDelAll').on('click', function () {
                self.__Flowdesigner.applyQuestion(self._getLang('table.subflow.delAll'), function () {
                    tblNodeSubflow.removeRow();
                    self._initSubflowSel(popWin, null);
                    self._chgApplyBtn(popWin.find('#applyBtn'), false);
                });
            });
            popWin.find('input[name="wait"]').on('change', function () {
                if (this.checked) {
                    //选中时,只需要把radio恢复
                    popWin.find(':radio[name="varType"][value$="OUT"]').prop('disabled', false);
                } else {
                    //需要判断现有的列表中是否包含了OUT
                    var isHave = false;
                    $.each(tblNodeSubflow.rows() || [], function (i, row) {
                        if (row) {
                            $.each(row.paras || [], function (j, para) {
                                if (para && para['type'].indexOf('OUT') != -1) {
                                    isHave = true;
                                    return false;
                                }
                            });
                            if (isHave) {
                                return false;
                            }
                        }
                    });
                    if (isHave) {
                        self._showMsg(self._getLang('table.subflow.set'));//('流程变量传递设置中存在[接受自][双向]时不能取消此设置');
                        this.checked = true;
                        return;
                    }
                    popWin.find(':radio[name="varType"][value="IN"]').prop('checked', true);
                    popWin.find(':radio[name="varType"][value$="OUT"]').prop('disabled', true);
                }
            });


            //子流程与主流程变量之间的设置表格初始化
            self._initSubParaTable(popWin, tblNodeSubflow, mainVars);
            //子流程启动时的办理人设置范围
            self._initSubAuthorTable(popWin);
        },
        //
        _initSubParaTable: function (popWin, tblNodeSubflow, mainVars) {
            var self = this;
            var tblNodeSubPara = popWin.find('#tblNodeSubPara').mmGrid({
                height: 120
                ,delTitle:self._getLang('table.field.defTitle')
                ,showCol:self._getLang('table.field.showCol')
                , cols: this._getNodeSubParaTableCol(mainVars)
                , items: []      //本地数据

                , multiSelect: false
                , fullWidthRows: true
                , autoLoad: false
                , loadingText: self._getLang('table.subvar.load')//'正在加载变量列表...'
                , noDataText: self._getLang('table.subvar.nodata')//'请添加主子流程变量交互方式'
            });
            tblNodeSubPara
                .on('cellSelected', function (e, item, rowIndex, colIndex) {
                    //判断当前数据是否被选中
                    var selectIndex = tblNodeSubPara.selectedRowsIndex();
                    if (selectIndex[0] == rowIndex) {
                        //取消选中
                        self._initSubParaSel(popWin, null);
                        // popWin.find('#btnSubParaAdd').text('添加');
                    } else {
                        self._initSubParaSel(popWin, item);
                        // popWin.find('#btnSubParaAdd').text('应用');
                    }
                })
                .load();
            this.tblObjArr['tblNodeSubPara'] = tblNodeSubPara;

            popWin.find('#btnSubParaAdd').on('click', function () {
                self._makeSubParaItem(popWin, tblNodeSubflow, tblNodeSubPara);
            });
            popWin.find('#btnSubParaDel').on('click', function () {
                if (self.__Flowdesigner.delCheckSel(tblNodeSubPara)) {
                    return;
                }
                self.__Flowdesigner.applyQuestion(self._getLang('table.subvar.del'), function () {
                    tblNodeSubPara.removeRow(tblNodeSubPara.selectedRowsIndex());
                    var flow = tblNodeSubflow.selectedRows();
                    if(tblNodeSubPara.rows()[0]){
                        flow[0].paras = tblNodeSubPara.rows();
                    }else{
                        flow[0].paras = [];
                    }
                    self._initSubParaSel(popWin, null);
                    self._chgApplyBtn(popWin.find('#applyBtn'), false);
                });
            });
            popWin.find('#btnSubParaDelAll').on('click', function () {
                self.__Flowdesigner.applyQuestion(self._getLang('table.subvar.delAll'), function () {
                    tblNodeSubPara.removeRow();
                    var flow = tblNodeSubflow.selectedRows();
                    flow[0].paras = [];
                    self._initSubParaSel(popWin, null);
                    self._chgApplyBtn(popWin.find('#applyBtn'), false);
                });
            });
        },
        //
        _initSubAuthorTable: function (popWin) {
            var self = this;
            var userOrg = popWin.find('#divSubAuthor');
            //子流程创建人设置范围表格ID
            var userOrgKey = 'tblNodeSubAuthor';
            var data = {};
            this.__Flowdesigner.initOrgDataTable(userOrg, this.tblObjArr, userOrgKey, 100, function (flag) {
                var tblNodeSubflow = self.tblObjArr['tblNodeSubflow'];
                var selSubItem = tblNodeSubflow.selectedRows();
                var tblNodeSubAuthor = self.tblObjArr['tblNodeSubAuthor'];
                if (selSubItem && selSubItem[0]) {
                    //不论时删除还是添加,都重新赋值
                    var author = {
                        person: '',
                        dept: '',
                        group: '',
                        position: ''
                    };
                    $.each(tblNodeSubAuthor.rows() || [], function (i, item) {
                        if (item && item['data']) {
                            author[item.type] += item['data'] + ';';
                        }
                    });
                    selSubItem[0]['Author'] = author;
                } else {
                    tblNodeSubAuthor.removeRow();
                    self.__Flowdesigner.applyQuestion(self._getLang('html.node.sub.a10'));
                }
            });
        },

        //点击子流程列表时的处理
        _initSubflowSel: function (popWin, item) {
            var self = this;
            //1.清空列表,2.清空子流程变量下拉框
            this.tblObjArr['tblNodeSubPara'].removeRow();
            popWin.find('select[name="subVar"]').empty();
            if (item == null) {
                return;
            }
            //选中时,1.初始化列表,2,初始化子流程下拉框
            //1.需要先获取子流程的所有变量列表
            if (item.vars) {
                self._initSubVars(popWin, item, item.vars);
            } else {
                self.__Flowdesigner.getSubFlowVarsFromServer(item.id, function (data) {
                    item.vars = data.vars;
                    self._initSubVars(popWin, item, data.vars);
                });
            }

            //2.对当前子流程对应的启动人列表进行处理
            var tblNodeSubAuthor = this.tblObjArr['tblNodeSubAuthor'];
            tblNodeSubAuthor.removeRow();//先清空
            var data = item['Author'];
            self.__Flowdesigner.initOrgDataItem(data, self.tblObjArr, 'tblNodeSubAuthor', false);
        },
        // 初始化子流程列表
        _initSubVars: function (popWin, item, allVars) {
            this.__Flowdesigner.initSelectOptions(
                popWin.find('select[name="subVar"]'), allVars);
            var tbl = this.tblObjArr['tblNodeSubPara'];
            $.each(item.paras || [], function (i, para) {
                if (para) {
                    para.vars = allVars;
                    tbl.addRow(para);
                }
            });
        },
        _initSubParaSel: function (popWin, item) {
            if (item == null) {
                popWin.find(':radio[name="varType"][value="IN"]').prop('checked', true);
            } else {
                popWin.find('select[name="mainVar"]').val(item.mainVar);
                popWin.find('select[name="subVar"]').val(item.subVar);
                popWin.find(':radio[name="varType"][value="' + item.type + '"]').prop('checked', true);
            }
        },

        _getNodeSubflowTableCol: function () {
            var title = this._getLang('table.subflow.title');
            return [
                {
                    title: title[0],//'子流程名称',
                    name: 'name',
                    width: 480
                },
                {
                    title: title[1],//'子流程ID',
                    name: 'id',
                    width: 455
                }
            ];
        },
        _getNodeSubParaTableCol: function (mainVars) {
            var title = this._getLang('table.subvar.title');
            var tType = this._getLang('table.subvar.type');
            return [
                {
                    title: title[0],//'主流程变量名称',
                    name: 'mainVar',
                    width: 205,
                    renderer: function (val, item, rowIndex) {
                        var label = val;
                        $.each(mainVars || [], function (i, data) {
                            if (data && data.data == val) {
                                label = data.label;
                                return false;
                            }
                        });
                        return label;
                    }
                },
                {
                    title: title[1],// '主流程变量ID',
                    name: 'mainVar',
                    width: 220
                },
                {
                    title: title[2],//'输入/输出',
                    name: 'type',
                    width: 180,
                    renderer: function (val, item, rowIndex) {
                        return tType[val];
                        // if(val == 'IN'){
                        //     return tType[0];//'输出至';
                        // }
                        // else if(val == 'OUT'){
                        //     return tType[1];// '接受自';
                        // }
                        // else if(val == 'INOUT'){
                        //     return tType[2];// '双向';
                        // }
                    }
                },
                {
                    title: title[3],//'子流程变量名称',
                    name: 'subVar',
                    width: 165,
                    renderer: function (val, item, rowIndex) {
                        var label = val;
                        $.each(item.vars || [], function (i, data) {
                            if (data && data.data == val) {
                                label = data.label;
                                return false;
                            }
                        });
                        return label;
                    }
                },
                {
                    title: title[4],// '子流程变量ID',
                    name: 'subVar',
                    width: 165
                }
            ];
        },
        _makeSubParaItem: function (popWin, tblNodeSubflow, tblNodeSubPara) {
            var isAdd = true;
            var mainId = popWin.find('select[name="mainVar"]').val();
            var subId = popWin.find('select[name="subVar"]').val();
            var varType = popWin.find(':radio[name="varType"]:checked').val();
            if (!varType) {
                this._showMsg(this._getLang('table.subvar.flag'));//('请选择传输方式');
                return;
            }
            var flow = tblNodeSubflow.selectedRows();
            var oldMid = '';
            var oldSid = '';
            var para = tblNodeSubPara.selectedRows();

            if (para && para[0]) {
                oldMid = para[0]['mainVar'];
                oldSid = para[0]['subVar'];
            }
            //如果是修改时
            if (mainId == oldMid && subId == oldSid) {
                isAdd = false;
                para[0]['type'] = varType;
                var selIndex = tblNodeSubPara.selectedRowsIndex();
                tblNodeSubPara.updateRow(para[0], selIndex[0]);
            } else {
                $.each(tblNodeSubPara.rows() || [], function (i, item) {
                    if (item && item['mainVar'] == mainId && item['subVar'] == subId) {
                        isAdd = false;
                        return false;
                    }
                });
                if (!isAdd) {
                    this._showMsg(this._getLang('table.subvar.exist'));//('修改后的主流程变量和子流程变量已经存在列表中');
                    return;
                }
            }

            if (isAdd) {
                if (para && para[0]) {
                    para[0]['type'] = varType;
                    para[0]['mainVar'] = mainId;
                    para[0]['subVar'] = subId;
                    var selIndex = tblNodeSubPara.selectedRowsIndex();
                    tblNodeSubPara.updateRow(para[0], selIndex[0]);
                } else {
                    var item = {};
                    item['type'] = varType;
                    item['mainVar'] = mainId;
                    item['subVar'] = subId;
                    item['vars'] = flow[0]['vars'];
                    tblNodeSubPara.addRow(item);
                    tblNodeSubPara.select(tblNodeSubPara.rowsLength() - 1);
                }
            }
            //更新子流程列表数据
            flow[0]['paras'] = tblNodeSubPara.rows();
            this._chgApplyBtn(popWin.find('#applyBtn'), false);
        },

        //异常初始化
        _initException: function (popWin, node) {
            var table = popWin.find('#tblNodeException');
            if (table.length == 0) {
                return;
            }
            var self = this;
            //异常名称下拉框初始化
            var excNameSelect = popWin.find('select[name="exceptionName"]');
            excNameSelect.empty();
            var exceptions = this.options.exceptions;
            $.each(node.exceptions || [], function (i, key) {
                excNameSelect.append('<option value="' + key + '">' + exceptions[key] + '</option>');
            });
            excNameSelect.append('<option value="WFE_0000">' + self._getLang('prop.custome') + '</option>');
            var codeObj = popWin.find('input[name="exceptionCode"]');
            codeObj.val(excNameSelect.val());
            codeObj.on('keyup', function () {
                self.__Flowdesigner.checkInputCharNumber($(this), 20);
            });
            popWin.find('input[name="exName"]').val(excNameSelect.find('option:selected').text());

            excNameSelect.on('change', function () {

                codeObj.val(this.value);
                popWin.find('input[name="exName"]').val(this.options[this.selectedIndex].label);
                popWin.find('input[name="exName"]').show();

                if (this.value == 'WFE_0000') {
                    codeObj.removeAttr('disabled');
                    popWin.find('input[name="exName"]').show();
                    popWin.find('input[name="exName"]').val('');
                    codeObj.val('');
                } else {
                    codeObj.attr('disabled', true);
                    popWin.find('input[name="exName"]').hide();
                }
            });

            //消息发送选择框
            var sendMsg = '';
            var defMsgSel = self.options['defSendMsg'] || '';
            $.each(this.options.sendMsg, function (key, label) {
                sendMsg += '<label class="checkbox-inline">' +
                    '<input type="checkbox"  name="exceptionMsg"' +
                    ' value="' + key + '" ' + (defMsgSel.indexOf(key) != -1 ? 'checked' : '') + '/>' + label +
                    '</label>'
            });
            popWin.find('#tdExceptionMsg').html(sendMsg);
            var defMsg = popWin.find('input[name="exceptionMsg"][value="Read"]');
            defMsg.attr('checked', true);
            defMsg.attr('disabled', true);

            //通知对象下拉框
            var sendUser = popWin.find('select[name="exceptionUser"]');
            sendUser.empty();
            $.each(this.options.sendUser, function (i, item) {
                sendUser.append('<option value="' + item.data + '">' + item.label + '</option>');
            });

            //处理方式类型下拉框
            var dealType = popWin.find('select[name="exceptionDealType"]');
            dealType.empty();
            $.each(this.options.dealType, function (i, item) {
                dealType.append('<option value="' + item.data + '">' + item.label + '</option>');
            });
            dealType.on('change', function () {
                var exceptionDeal = popWin.find('input[name="exceptionDeal"]');
                var exceptionDealMsg = popWin.find('.exceptionDeal');
                exceptionDeal.val('');
                exceptionDeal.attr('data', '');
                if (this.value == '0' || this.value == '2') {
                    //自定义
                    exceptionDeal.show();
                    exceptionDealMsg.show();
                    exceptionDeal.off('click');
                    if (this.value == '2') {
                        //跳转
                        exceptionDeal.prop('readonly', true);
                        exceptionDeal.on('click', function () {
                            self._selectNodeAndBack(node,
                                function (data) {
                                    if (data && data.length > 0) {//有可能是一个也不选择,想清空的情况
                                        exceptionDeal.val(data[0].label);
                                        exceptionDeal.attr('data', data[0].data);
                                    } else {
                                        exceptionDeal.val('');
                                        exceptionDeal.attr('data', '');
                                    }
                                },
                                false, exceptionDeal.attr('data') + ';',
                                function (item) {
                                    if (item.id == node.id) {
                                        return false; //不能选择自己
                                    }
                                    return true;
                                }
                            );
                        });
                    } else {
                        exceptionDeal.prop('readonly', false);
                    }
                } else {
                    exceptionDeal.hide();
                    exceptionDealMsg.hide();
                }
            });

            var items = [];
            $.each(node.data.exceptions || [], function (key, item) {
                if (item) {
                    items.push(item);
                }
            });

            var initData = {
                code: '',   //异常代码
                name: '',   //异常名称
                dealType: '1',//异常处理类型0 自定义 1 无 2 跳转 3 挂起 4 终止
                deal: '',   //处理方式根据类型不同,对应的内容不同
                user: '1',   //消息接收人
                msg: 'Read'     //发送消息
            };

            var tblNodeException = table.mmGrid({
                height: 190
                ,delTitle:self._getLang('table.field.defTitle')
                ,showCol:self._getLang('table.field.showCol')
                , cols: this._getNodeExceptionTableCol()
                , items: items      //本地数据

                , multiSelect: false
                , fullWidthRows: true
                , autoLoad: false
                , loadingText: self._getLang('table.exception.load')//'正在加载异常列表...'
                , noDataText: self._getLang('table.exception.nodata')//'请添加异常'
            });
            //加载表格
            tblNodeException
                .on('cellSelected', function (e, item, rowIndex, colIndex) {
                    //判断当前数据是否被选中
                    var selectIndex = tblNodeException.selectedRowsIndex();
                    if (selectIndex[0] == rowIndex) {
                        //取消选中
                        self._initExceptionSel(popWin, initData);
                        popWin.find('#btnExceptionAdd').text(self._getLang('prop.add'));//('添加');
                    } else {
                        self._initExceptionSel(popWin, item);
                        popWin.find('#btnExceptionAdd').text(self._getLang('prop.apply'));//('应用');
                    }
                })
                .load();
            //记录表格对象,为确认保存数据使用
            this.tblObjArr['tblNodeException'] = tblNodeException;

            popWin.find('#btnExceptionAdd').on('click', function () {
                if (popWin.find('input[name="exName"]').val() == '') {
                    self._showMsg(self._getLang('table.exception.sel'));//('请选择异常名称');
                    return;
                } else if (popWin.find('select[name="exceptionName"]').val() == 'WFE_0000') {
                    if (popWin.find('input[name="exName"]').val() == '') {
                        self._showMsg(self._getLang('table.exception.iname'));//('请输入自定义的异常名称');
                        return;
                    }
                    if (popWin.find('input[name="exceptionCode"]').val() == '') {
                        self._showMsg(self._getLang('table.exception.icode'));//('请输入自定义的异常代码');
                        return;
                    }
                }

                var type = popWin.find('select[name="exceptionDealType"]').val();
                if (type == '0' || type == '2') {
                    var deal = popWin.find('input[name="exceptionDeal"]');
                    var val = type == '0' ? deal.val() : deal.attr('data');
                    if (val == '') {
                        self._showMsg(self._getLang(type == '0' ? 'table.exception.dealfalg' : 'table.exception.jumpnode'));//'请输入自定义的处理方式':'请选择要跳转到的节点');
                        return;
                    }
                }
                var selIndex = tblNodeException.selectedRowsIndex();
                var allRows = tblNodeException.rows();
                if (selIndex.length == 1) {
                    var selItem = tblNodeException.selectedRows();
                    var oldId = selItem[0]['code'];
                    var item = self._makeExceptionItem(popWin, allRows, oldId);
                    if (item == null) {
                        self._showMsg(self._getLang('table.exception.chgexist'));//('修改后的异常已经存在,每种类型只能添加一次');
                        return;
                    }
                    tblNodeException.updateRow(item, selIndex[0]);
                } else {
                    var item = self._makeExceptionItem(popWin, allRows, null);
                    if (item == null) {
                        self._showMsg(self._getLang('table.exception.exist'));//('异常已经存在');
                        return;
                    }
                    tblNodeException.addRow(item);
                    //添加后不自动选中,以便能够连续添加
                    // tblNodeException.select(tblNodeException.rowsLength()-1);
                    // popWin.find('#btnExceptionAdd').text('应用');
                }
                self._chgApplyBtn(popWin.find('#applyBtn'), false);
            });
            popWin.find('#btnExceptionDel').on('click', function () {
                if (self.__Flowdesigner.delCheckSel(tblNodeException)) {
                    return;
                }
                self.__Flowdesigner.applyQuestion(self._getLang('table.exception.del'), function () {
                    tblNodeException.removeRow(tblNodeException.selectedRowsIndex());
                    self._initExceptionSel(popWin, initData);
                    self._chgApplyBtn(popWin.find('#applyBtn'), false);
                });
            });
            popWin.find('#btnExceptionDelAll').on('click', function () {
                self.__Flowdesigner.applyQuestion(self._getLang('table.exception.delAll'), function () {
                    tblNodeException.removeRow();
                    self._initExceptionSel(popWin, initData);
                    self._chgApplyBtn(popWin.find('#applyBtn'), false);
                });
            });
        },
        _getNodeExceptionTableCol: function () {
            var self = this;
            var msg = this.options.sendMsg;
            var sendUser = this.options.sendUser;
            var dealType = this.options.dealType;
            var title = self._getLang('table.exception.title');
            return [
                {
                    title: title[0],//'异常名称',
                    name: 'name',
                    width: 250,
                    lockWidth: true
                },
                {
                    title: title[1],//'异常代码',
                    name: 'code',
                    width: 150,
                    lockWidth: true
                },
                {
                    title: title[2],//'异常消息',
                    name: 'msg',
                    width: 280,
                    renderer: function (val, item, rowIndex) {
                        var result = '';
                        $.each(val.split(';') || [], function (i, msgItem) {
                            if (msgItem) {
                                result += ';' + msg[msgItem];
                            }
                        });
                        return result.substring(1);
                    }
                },
                {
                    title: title[3],//'通知对象',
                    name: 'user',
                    width: 100,
                    lockWidth: true,
                    renderer: function (val, item, rowIndex) {
                        var label = '';
                        $.each(sendUser, function (i, user) {
                            if (user.data == val) {
                                label = user.label;
                                return false;
                            }
                        });
                        return label;
                    }
                },
                {
                    title: title[4],//'异常处理',
                    name: 'dealType',
                    width: 160,
                    lockWidth: true,
                    renderer: function (val, item, rowIndex) {
                        var label = '';
                        $.each(dealType, function (i, deal) {
                            if (val == deal['data']) {
                                label = deal['label'];
                                return false;
                            }
                        })
                        if (val == '0' || val == '2') {
                            label += '(' + item.deal + ')';
                        }
                        return label;
                    }
                }
            ]
        },
        _initExceptionSel: function (popWin, item) {
            var exCode = popWin.find('input[name="exceptionCode"]');
            var exNameSel = popWin.find('select[name="exceptionName"]');
            var exName = popWin.find('input[name="exName"]');

            exNameSel.val(item['code']);
            exCode.val(item['code']);
            exName.val(item['name']);

            //自定义处理
            exName.hide();
            exCode.attr('disabled', true);

            var selVal = exNameSel.val();
            if (!selVal) {
                if (item['code']) {//自定义
                    exNameSel.val('WFE_0000');
                    exName.show();
                    exCode.removeAttr('disabled');
                } else {//取消选择时
                    exNameSel.val('');
                    exName.val('');
                }
            }

            popWin.find('select[name="exceptionUser"]').val(item['user']);
            var deal = popWin.find('input[name="exceptionDeal"]');
            var dealType = popWin.find('select[name="exceptionDealType"]');
            dealType.val(item['dealType']);
            dealType.change();//让exceptionDeal绑定事件

            if (item['dealType'] == '0') {
                deal.show();
                deal.val(item['deal']);
                deal.attr('data', '');
                deal.prop('readonly', false);
            } else if (item['dealType'] == '2') {
                deal.show();
                deal.prop('readonly', true);
                deal.attr('data', item['deal']);
                deal.val(this.__Flowdesigner.curDrawLayer._nodes[item['deal']].name
                    + '(' + item['deal'] + ')');
            } else {
                deal.hide();
                deal.val('');
            }

            //消息
            $.each(this.options.sendMsg, function (key, label) {
                popWin.find('input[name="exceptionMsg"][value="' + key + '"]').prop('checked', false);
            });
            $.each(item['msg'].split(";") || [], function (i, item) {
                if (item) {
                    popWin.find('input[name="exceptionMsg"][value="' + item + '"]').prop('checked', true);
                }
            })
        },
        _makeExceptionItem: function (popWin, allItem, ignoreId) {
            var isHave = false;
            var newId = popWin.find('input[name="exceptionCode"]').val();
            $.each(allItem || [], function (i, item) {
                if (item && item['code'] != ignoreId && item['code'] == newId) {
                    isHave = true;
                    return false;
                }
            });
            if (isHave) {
                return null;
            }
            var item = {};
            item['code'] = newId;
            item['name'] = popWin.find('input[name="exName"]').val();
            item['user'] = popWin.find('select[name="exceptionUser"]').val();
            item['dealType'] = popWin.find('select[name="exceptionDealType"]').val();
            item['deal'] = item['dealType'] == '2' ?
                popWin.find('input[name="exceptionDeal"]').attr('data') :
                popWin.find('input[name="exceptionDeal"]').val();
            var msg = '';
            $.each(this.options.sendMsg, function (key, label) {
                if (popWin.find('input[name="exceptionMsg"][value="' + key + '"]').prop('checked')) {
                    msg += ';' + key;
                }
            });

            item['msg'] = msg.substring(1);
            return item;
        },

        //节点参数
        _initNodePara: function (popWin, node) {
            var table = popWin.find('#tblNodePara');
            if (table.length == 0) {
                return;
            }
            var self = this;
            var items = [];
            $.each(node.data.paras || [], function (key, item) {
                if (item) {
                    items.push(item);
                }
            });

            var initData = {
                id: '',
                name: '',
                value: ''
            };
            var tblNodePara = table.mmGrid({
                height: 260
                ,delTitle:self._getLang('table.field.defTitle')
                ,showCol:self._getLang('table.field.showCol')
                , cols: this._getNodeParaTableCol()
                , items: items      //本地数据

                , multiSelect: false
                , fullWidthRows: true
                , autoLoad: false
                , loadingText: self._getLang('table.para.load')//'正在加载节点参数列表...'
                , noDataText: self._getLang('table.para.nodata')//'请添加节点参数'
            });
            //加载表格
            tblNodePara
                .on('cellSelected', function (e, item, rowIndex, colIndex) {
                    //判断当前数据是否被选中
                    var selectIndex = tblNodePara.selectedRowsIndex();
                    if (selectIndex[0] == rowIndex) {
                        //取消选中
                        self._initParaSel(popWin, initData);
                        popWin.find('#btnParaAdd').text(self._getLang('prop.add'));//('添加');
                    } else {
                        self._initParaSel(popWin, item);
                        popWin.find('#btnParaAdd').text(self._getLang('prop.apply'));//('应用');
                    }
                })
                .load();
            //记录表格对象,为确认保存数据使用
            this.tblObjArr['tblNodePara'] = tblNodePara;

            popWin.find('input[name="paraId"]').on('keyup', function () {
                self.__Flowdesigner.checkInputCharNumber($(this));
            });
            popWin.find('#btnParaAdd').on('click', function () {
                if (popWin.find('input[name="paraId"]').val() == '') {
                    self._showMsg(self._getLang('table.para.idnull'));//('参数ID不能为空');
                    return;
                }
                if (popWin.find('input[name="paraName"]').val() == '') {
                    self._showMsg(self._getLang('table.para.namenull'));//('参数名称不能为空');
                    return;
                }

                var selIndex = tblNodePara.selectedRowsIndex();
                var allRows = tblNodePara.rows();
                if (selIndex.length == 1) {
                    var selItem = tblNodePara.selectedRows();
                    var oldId = selItem[0]['id'];
                    var item = self._makeParaItem(popWin, allRows, oldId);
                    if (item == null) {
                        self._showMsg(self._getLang('table.para.chgexist'));//('修改后的参数ID已经存在');
                        return;
                    }
                    tblNodePara.updateRow(item, selIndex[0]);
                } else {
                    var item = self._makeParaItem(popWin, allRows, null);
                    if (item == null) {
                        self._showMsg(self._getLang('table.para.exist'));//('参数ID已经存在');
                        return;
                    }
                    tblNodePara.addRow(item);
                    //20201105 LIYS 去掉默认选中,否则添加多个时有点烦人
                    //tblNodePara.select(tblNodePara.rowsLength()-1);
                    //popWin.find('#btnParaAdd').text(self._getLang('prop.apply'));//('应用');
                }
                self._chgApplyBtn(popWin.find('#applyBtn'), false);
            });
            popWin.find('#btnParaDel').on('click', function () {
                if (self.__Flowdesigner.delCheckSel(tblNodePara)) {
                    return;
                }
                self.__Flowdesigner.applyQuestion(self._getLang('table.para.del'), function () {
                    tblNodePara.removeRow(tblNodePara.selectedRowsIndex());
                    self._initParaSel(popWin, initData);
                    self._chgApplyBtn(popWin.find('#applyBtn'), false);
                });
            });
            popWin.find('#btnParaDelAll').on('click', function () {
                self.__Flowdesigner.applyQuestion(self._getLang('table.para.delAll'), function () {
                    tblNodePara.removeRow();
                    self._initParaSel(popWin, initData);
                    self._chgApplyBtn(popWin.find('#applyBtn'), false);
                });
            });
        },
        _makeParaItem: function (popWin, allItem, ignoreId) {
            var isHave = false;
            var newId = popWin.find('input[name="paraId"]').val();
            $.each(allItem || [], function (i, item) {
                if (item && item['id'] != ignoreId && item['id'] == newId) {
                    isHave = true;
                    return false;
                }
            });
            if (isHave) {
                return null;
            }
            var item = {};
            item['id'] = newId;
            item['name'] = popWin.find('input[name="paraName"]').val();
            item['value'] = popWin.find('input[name="paraValue"]').val();

            return item;
        },
        _initParaSel: function (popWin, item) {
            //取消选中
            popWin.find('input[name="paraId"]').val(item['id']);
            popWin.find('input[name="paraName"]').val(item['name']);
            popWin.find('input[name="paraValue"]').val(item['value']);

        },
        _getNodeParaTableCol: function () {
            var title = this._getLang('table.para.title');
            return [
                {
                    title: title[0],//'参数ID',
                    name: 'id',
                    width: 300,
                    lockWidth: true
                },
                {
                    title: title[1],//'参数名称',
                    name: 'name',
                    width: 300
                },
                {
                    title: title[2],//'默认值',
                    name: 'value',
                    width: 340,
                    lockWidth: true
                }
            ];
        },

        //操作初始化
        _initOperator: function (popWin, node) {
            var self = this;
            $.each(node.operators || [], function (i, participant) {
                self._initOperatorAction(popWin, participant, node);
                self._initOperatorForm(popWin, participant, node);
            });

            self.initActionLst(popWin, node, true);
        },
        _initOperatorAction: function (popWin, participant, node) {
            var data = node.data.authDo[participant];
            if (!data) {
                data = {
                    buttons: {
                        backNodes: '',
                        actions: {}
                    }
                }
            }
            var self = this;
            var actionKey = participant + '_nodeAction';
            var actionObj = popWin.find('#o' + actionKey);

            var backNode = actionObj.find('select[name="backNodes"]');
            var rejectNode = actionObj.find('select[name="rejectNodes"]');
            backNode.parent().hide();
            rejectNode.parent().hide();

            var funSel = function (tmpNode, dataKey, filterFun) {
                tmpNode.parent().show();
                var tmpnodes = data['buttons'][dataKey] || '';
                var allnode = node.__drawLayer._nodes;
                tmpNode.empty();
                //初始化已选择的项
                $.each(tmpnodes.split(';') || [], function (i, nodeid) {
                    if (nodeid && allnode[nodeid]) {
                        tmpNode.append('<option value="' + nodeid + '">' + allnode[nodeid].name + '(' + nodeid + ')</option>')
                    }
                });
                //节点约束选择,
                tmpNode.on('click', function () {
                    self._selectNodeAndBack(node,
                        function (data) {
                            tmpNode.empty();
                            $.each(data || [], function (i, item) {
                                if (item) {
                                    tmpNode.append('<option value="' + item['data'] + '">' + item['label'] + '</option>');
                                }
                            })
                            self._chgApplyBtn($('#applyBtn'), false);
                        },
                        true, self._getSelAllOptionsVal(tmpNode) + ';',
                        filterFun);
                });
            }

            if (node.getStatus() == 'task') {
                if (participant == 'Done') {
                    funSel(backNode, "backNodes", function (item) {
                        if (item.id == node.id) {
                            return false;
                        }
                        var back = false;
                        //判断item节点的路由是否指向node
                        $.each(item.routes || [], function (i, route) {
                            if (route && route.toNode.id == node.id) {
                                back = true;
                                return false;
                            }
                        });
                        return back;
                    });
                } else if (participant == 'Author') {
                    var rejectOther = actionObj.find('input[name="rejectOther"]');
                    rejectOther.parent().show();
                    rejectOther.prop('checked', node.data.rejectOther == '1');

                    funSel(rejectNode, "rejectNodes", function (item) {
                        if (item.id == node.id) {
                            return false;
                        }
                        return true;
                    });
                }
            }
            var items = [];

            var tblAction = actionObj.find('#tblAction').mmGrid({
                height: 266
                ,delTitle:self._getLang('table.field.defTitle')
                ,showCol:self._getLang('table.field.showCol')
                , cols: this._getActionTableCol()
                , items: items      //本地数据

                , multiSelect: false
                , fullWidthRows: true
                , autoLoad: false
                , loadingText: self._getLang('table.action.load')//'正在加载操作列表...'
                , noDataText: self._getLang('table.action.nodata')//'当前无可选操作'
            });
            tblAction
                .on('cellSelected', function (e, item, rowIndex, colIndex) {
                    if ($(e.target).is('.btn-default')) {
                        e.stopPropagation(); //阻止事件冒泡
                        var msg = self._getLang('table.action.msg')
                            .replace('ID', item.id)
                            .replace('CLASS', item.implClass)
                            .replace('MEMO', item.memo);
                        self._showMsg(msg);
                    } else if (!$(e.target).is('.form-control')) {
                        item.sel = !item.sel;
                        tblAction.load(tblAction.rows());
                        self._chgApplyBtn(popWin.find('#applyBtn'), false);
                    }
                })
                .on('loadSuccess', function (e, data) {
                    actionObj.find('.nameChg').on('keyup', function () {
                        var item = tblAction.rows();
                        item[this.name.split("_")[1]].reName = this.value;
                        self._chgApplyBtn(popWin.find('#applyBtn'), false);
                    });
                })
                .load();
            this.tblObjArr[actionKey] = tblAction;
            //应用到其他节点
            actionObj.find('#btnCopyToOter').on('click', function () {
                self.selectNodeMulti(node,
                    function (selnode) {
                        self._copyActionToOther(popWin, node, participant, tblAction, selnode);
                    },
                    function (item) {
                        //如果节点没有当前的页签,直接过滤掉
                        if (item.operators.indexOf(participant) == -1) {
                            return false;
                        }
                        return true;
                    }
                );
            });
        },
        _getSelAllOptionsVal: function (selObj) {
            var selVal = '';
            $.each(selObj.find('option') || [], function (i, option) {
                if (option) {
                    selVal += ';' + option.value;
                }
            });
            return selVal == '' ? '' : selVal.substring(1);
        },
        //拷贝操作设置到其他节点,
        _copyActionToOther: function (popWin, node, participant, tblAction, selnode) {
            // console.log(node.id+'--->'+participant +'--->'+selnode);
            //1.先获取当前选择的操作结果
            var self = this;
            var copyObj = {buttons: {}};
            this._applyOperatorAction(popWin, participant, copyObj['buttons'], copyObj);
            //2.对选择的节点进行类型匹配,确定是否具有当前拷贝的权限
            var allNodes = node.__drawLayer._nodes;
            $.each(selnode.val() || [], function (i, nodeid) {
                if (!nodeid) {
                    return true;
                }
                var targetNode = allNodes[nodeid];
                //下面的条件判断在所有节点筛选时已经处理了
                // if(targetNode.operators.indexOf(participant) ==-1){
                //     return true;
                // }
                var targetData = targetNode.data;
                var targetButton = {};
                //有相同的页签,也可能因为节点类型不同,有些操作需要过滤处理
                if (participant == 'Author') {
                    targetData['rejectOther'] = copyObj['rejectOther'];
                }
                //已办约束条件,不能拷贝,节点不同
                //targetButton['backNodes'] = copyObj['buttons']['backNodes'];
                //采用增量的方式拷贝,如果需要全覆盖,则打开下面的语句即可
                // targetButton['actions'] ={};
                //针对选中的每个操作进行判断是否应该在目标节点中
                var nodeType = targetNode.nodetype;
                var nodeStatus = targetNode.getStatus();
                $.each(copyObj['buttons']['actions'] || [], function (key, action) {
                    if (!action) {
                        return true;
                    }
                    var operator = self.options.operators[key];
                    if (node.checkActionShow(nodeType, nodeStatus, operator['node'])) {
                        targetButton[key] = action;
                    }
                });
                targetData.authDo[participant]['buttons']['actions'] = targetButton;
            });
            self._showMsg(self._getLang('static.copyover'))
        },
        //初始化时/切换节点类型时
        initActionLst: function (popWin, node, init, nodeType) {
            var self = this;
            if (!nodeType) {
                nodeType = node.nodetype;
            }
            var nodeStatus = node.getStatus();
            $.each(node.operators || [], function (i, participant) {
                var actions = self._initActionDefData(node, participant, init);
                var items = [];
                var defActions = self.options.defOperator[participant];

                $.each(self.options.operators[participant], function (i, value) {
                    //某一操作的定义信息
                    var operator = self.options.operators[value];
                    if (node.checkActionShow(nodeType, nodeStatus, operator['node'])) {
                        var id = operator['id'];
                        var reName = operator['reName'];
                        if (actions && actions[id]) {
                            reName = actions[id]['reName'] || reName;
                        }
                        items.push({//actions==null时按照defActions选择
                            sel: self._checkActionSel(actions, id, defActions),
                            id: id,
                            name: operator['name'],
                            reName: reName,
                            implClass: operator['implClass'],
                            memo: operator['memo']
                        })
                    }
                });

                self.tblObjArr[participant + '_nodeAction'].load(items);
            });
        },
        _initActionDefData: function (node, participant, init) {
            if (init) {
                var data = node.data.authDo[participant];
                if (!data) {
                    return null;
                }
                return data.buttons['actions'];
            } else {
                var buttons = {};
                $.each(this.tblObjArr[participant + '_nodeAction'].rows() || [], function (i, item) {
                    if (item && item.sel) {
                        buttons[item.id] = item;
                    }
                });
                return buttons;
            }
        },
        //判断一个操作是否应该默认被选中
        _checkActionSel: function (actions, id, defActions) {
            var isHave = false;
            if (actions == null) {
                $.each(defActions || [], function (i, value) {
                    if (value == id) {
                        isHave = true;
                        return false;
                    }
                });
            } else {
                $.each(actions || [], function (key, item) {
                    if (key == id) {
                        isHave = true;
                        return false;
                    }
                });
            }

            return isHave;
        },
        _getActionTableCol: function () {
            var title = this._getLang('table.action.title');
            return [
                {
                    title: title[0],//'选择',
                    name: 'sel',
                    width: 50,
                    align: 'center',
                    lockWidth: true,
                    renderer: function (val, item, rowIndex) {
                        return '<div class="' + (val ? 'tableRowSelect' : 'tableRowNoSelect') + '"></div>';
                    }
                },
                {
                    title: title[1],//'名称',
                    name: 'name',
                    width: 150,
                    lockWidth: true
                },
                {
                    title: title[2],//'别名',
                    name: 'reName',
                    width: 115,
                    lockWidth: true,
                    renderer: function (val, item, rowIndex) {
                        return '<input type="text" name="reName_' + rowIndex + '" value="' + (val ? val : '') + '" class="form-control checkChange nameChg">'
                    }
                },
                {
                    title: title[3],//'实现类',
                    name: 'implClass',
                    width: 295
                },
                {
                    title: title[4],//'详情',
                    name: 'id',
                    width: 70,
                    align: 'center',
                    lockWidth: true,
                    renderer: function (val, item, rowIndex) {
                        return '<button class="btn btn-default btn-sm">' + title[5] + '</button>';
                    }
                }
            ];
        },

        _initOperatorForm: function (popWin, participant, node) {
            var data = node.data.authDo[participant];
            if (!data) {
                data = {
                    forms: {
                        dfId: '',
                        chg: 0
                    }
                }
            }
            var self = this;
            var formKey = participant + '_nodeForm';
            var formObj = popWin.find('#o' + formKey);
            var allForms = node.__drawLayer.data.flowInfo['forms'];//所有已经定义的表单列表
            var defForm = formObj.find('select[name="defForm"]');
            var items = [];
            //默认显示表单下拉框初始化
            defForm.empty();
            var defId = data['forms']['dfId'];
            var chg = data['forms']['chg'];
            var chgForms = [];
            if ($.isEmptyObject(allForms)) {
                return
            }
            $.each(allForms || [], function (i, form) {
                if (!form) {
                    return true;
                }
                if (!defId && form.isMain == 1) {
                    defId = form.id;
                }
                var item = {
                    sel: false,
                    name: form.name,
                    group: form.group,

                    id: form.id,
                    buttons: '',
                    fieldControlId: participant.indexOf('Author') == -1 ? 'allreadonly' : 'alleditable'
                };
                //表单是否被选择的处理
                self._checkFormSel(item, allForms, data.forms['form']);
                //根据item.sel是否为true来确定是否在默认下拉框中显示
                var chgPush = true;
                if (item.sel) {
                    if (chg == 1) {
                        chgForms.push(item);
                        chgPush = false;
                    }
                    //打开时,初始化默认下拉框(不应该是全部)
                    defForm.append('<option value="' + form.id + '">' + form.name + '</option>');
                }
                if (chgPush) {
                    items.push(item);
                }

            });
            defForm.val(defId);
            //如果勾选了自行调整unshift()
            if (chgForms.length > 0) {
                if (chgForms.length == 1) {
                    items.unshift(chgForms[0]);
                } else {
                    //按排序调整
                    data.forms['form'] = this.__Flowdesigner.sortObject(data.forms['form'], 'id', 'sort');
                    //需要调整时
                    var tmpForms = [];
                    $.each(data.forms['form'], function (id, form) {
                        $.each(chgForms, function (i, item) {
                            if (form.id == item.id) {
                                tmpForms.push(item);
                                return false;//break;
                            }
                        });
                    });
                    for (var i = tmpForms.length - 1; i >= 0; i--) {
                        items.unshift(tmpForms[i]);
                    }
                }
            }

            var tblForm = formObj.find('#tblForm').mmGrid({
                height: 230
                ,delTitle:self._getLang('table.field.defTitle')
                ,showCol:self._getLang('table.field.showCol')
                , cols: this._getFormTableCol(self, popWin, participant)
                , items: items      //本地数据
                // , checkCol:true
                , multiSelect: false
                , fullWidthRows: true
                , autoLoad: false
                , loadingText: self._getLang('table.nform.load')//'正在加载表单列表...'
                , noDataText: self._getLang('table.nform.nodata')//'当前无可选表单'
            });
            tblForm
                .on('cellSelected', function (e, item, rowIndex, colIndex) {
                    if ($(e.target).is('.selBtn')) {
                        e.stopPropagation(); //阻止事件冒泡
                        self._selFormBtnClick(tblForm, $(e.target), item, rowIndex);
                    } else if ($(e.target).is('.fieldSel')) {
                        // e.stopPropagation(); //阻止事件冒泡
                    } else if ($(e.target).is('.fieldAdd')) {
                        e.stopPropagation(); //阻止事件冒泡
                        self._addFormFieldClick(node, item, tblForm, rowIndex);
                    } else if ($(e.target).is('.fieldEdit')) {
                        e.stopPropagation(); //阻止事件冒泡
                        self._editFormFieldClick(node, item);
                    } else if ($(e.target).is('.fieldCopy')) {
                        e.stopPropagation(); //阻止事件冒泡
                        self._copyFormFieldClick(node, participant, item);
                    } else if (colIndex < 1) {
                        //需要判断是否有分组的情况
                        if (item.group) {
                            $.each(tblForm.rows() || [], function (i, row) {
                                if (row && row.group == item.group) {
                                    if (i == rowIndex) {
                                        row.sel = !row.sel;
                                    } else if (row.sel) {
                                        row.sel = false;
                                    }
                                }
                            });
                        } else {
                            item.sel = !item.sel;
                        }
                        //更新所有数据
                        tblForm.load(tblForm.rows());
                        //更新默认表单列表框
                        self._chgDefFormSelect(defForm, tblForm);
                        self._chgApplyBtn(popWin.find('#applyBtn'), false);
                    }
                })
                .on('loadSuccess', function (e, data) {
                    self._bindChgFieldSel(formObj, tblForm);

                    var forms = {};
                    $.each(tblForm.rows(), function (i, row) {
                        // if(typeof(exp) != "undefined"){
                        forms[row.id] = row;
                        // }
                    });
                    self._initUserFiledSel(popWin, participant, forms);
                })
                .load();

            this.tblObjArr[formKey] = tblForm;

            //*
            // 允许自行调整
            var chgFormBtn = function (flag) {
                formObj.find('#btnUp').attr('disabled', !flag);
                formObj.find('#btnDown').attr('disabled', !flag);
            }
            formObj.find('input[name="chgForm"]').prop('checked', data['forms']['chg'] == 1);
            chgFormBtn(data['forms']['chg'] == 1);
            self._chgDefFormSelect(defForm, tblForm, true);

            formObj.find('input[name="chgForm"]').on('click', function () {
                chgFormBtn(this.checked);
            });
            var reSelRow = function (tblForm) {
                //记录选中的行号
                var selectedIndexes = tblForm.selectedRowsIndex();
                var index = selectedIndexes[0]; //只对被选中的第一条进行操作
                //更新所有数据(如不更新则下拉框不能触发应用按钮可用)
                tblForm.load(tblForm.rows());
                //重新选中,可用连续上下移动
                tblForm.select(index);
            }
            formObj.find('#btnUp').on('click', function () {
                self.__Flowdesigner.chgTableDataUpDown(tblForm, true);
                reSelRow(tblForm);
                self._chgDefFormSelect(defForm, tblForm, true);
                self._chgApplyBtn(popWin.find('#applyBtn'), false);
            });
            formObj.find('#btnDown').on('click', function () {
                self.__Flowdesigner.chgTableDataUpDown(tblForm, false);
                //更新所有数据
                reSelRow(tblForm);
                self._chgDefFormSelect(defForm, tblForm, true);
                self._chgApplyBtn(popWin.find('#applyBtn'), false);
            });
        },
        _chgDefFormSelect: function (defForm, tblObj) {
            var def = defForm.val();
            defForm.empty();
            var first = '';
            var group = '';
            $.each(tblObj.rows() || {}, function (i, row) {
                if (row) {
                    if (row.sel) {
                        defForm.append('<option value="' + row.id + '">' + row.name + '</option>');
                        if (first == '') {
                            first = row.id;
                        }
                    } else if (def == row.id && row.group) {
                        //默认表单被取消时,
                        group = row.group;
                    }
                }
            });
            if (group != '') {
                //分组的表单被取消时,判断同组是否有被选中的表单
                $.each(tblObj.rows() || {}, function (i, row) {
                    if (row && row.sel && row.group == group) {
                        def = row.id;
                    }
                });
            }
            //重置默认选项
            defForm.val(def);
            def = defForm.val();
            if (def == null) {
                //原来的默认表单被取消时,重新给予默认值
                defForm.val(first);
            }
        },


        _bindChgFieldSel: function (formObj, tblForm) {
            var self = this;
            formObj.find('.fieldSel').on('change', function () {
                self._chgFieldSel(tblForm, $(this));
            });
        },
        _chgFieldSel: function (tblForm, $this, item, rowIndex) {
            //字段权限下拉框变化时
            var editBtn = $this.next();
            if ($this.val() == 'alleditable' || $this.val() == 'allreadonly') {
                editBtn.prop('disabled', true);
            } else {
                editBtn.prop('disabled', false);
            }
            if (!rowIndex) {
                rowIndex = $this.parent().parent().parent().index();
            }
            if (!item) {
                item = tblForm.row(rowIndex);
            }
            item.fieldControlId = $this.val();

            tblForm.load(tblForm.rows());
            this._chgApplyBtn($('#applyBtn'), false);
        },
        _selFormBtnClick: function (tblForm, $this, item, rowIndex) {
            //选择指定表单的按钮
            //已经获取到的表单信息
            var formInfo = this.__Flowdesigner.curDrawLayer.forms;
            var form = formInfo[item.id];//['buttons'];
            if (form) {
                if (form && form['buttons']) {
                    this._selectFormButton(form['buttons'], item['buttons'], function (buttons) {
                        item['buttons'] = buttons != null ? buttons.join(';') : '';
                        tblForm.updateRow(item, rowIndex);
                    });
                }
            } else {
                this._showMsg(this._getLang('table.nform.loaderr'));//('表单数据获取异常');
                //没有加载过表单信息(在流程加载时,执行加载,选择表单时也从后台获取)
            }
        },
        _addFormFieldClick: function (node, item, tblForm, rowIndex) {
            this._editFieldPage(node, item, true, function (id) {
                //从tblForm中
                tblForm.row(rowIndex).fieldControlId = id;
                tblForm.load(tblForm.rows());
            });
        },
        _editFormFieldClick: function (node, item) {
            this._editFieldPage(node, item, false);
        },
        _copyFormFieldClick: function (node, participant, item) {
            var self = this;
            var buttons = item.buttons;
            var controlId = item.fieldControlId;
            var formId = item.id;
            var defFormId = node.data.authDo[participant]['forms']['dfId'];
            this._selectFormApply(node, participant, item.sel, function (rows) {
                var allNodes = node.__drawLayer._nodes;
                var allForms = node.__drawLayer.data.flowInfo['forms'];//所有已经定义的表单列表
                var group = {};
                //获取到所有分组内的表单ID
                $.each(allForms || [], function (id, form) {
                    if (form && form.group) {
                        if (!group[form.group]) {
                            group[form.group] = [];
                        }
                        group[form.group].push(id);
                    }
                });

                $.each(rows || [], function (i, row) {
                    if (!row) {
                        return true;
                    }
                    if (!row.sel) {
                        return true;
                    }
                    var targetNode = allNodes[row.id];//nodeid
                    var targetData = targetNode.data.authDo[participant]['forms']['form'];
                    targetNode.data.authDo[participant]['forms']['dfId'] = defFormId;
                    if (row.selForm) {
                        //分组处理
                        if (item.group) {
                            //如果当前表单有分组,则需要删除组内所有的表单
                            $.each(group[item.group] || [], function (i, id) {
                                if (id) {
                                    delete targetData[id];
                                }
                            });
                        }
                        targetData[formId] = {
                            id: formId,
                            buttons: buttons,
                            fieldControlId: controlId
                        };
                    } else {
                        delete targetData[formId];
                    }
                });

                self._showMsg(self._getLang('static.copyover'));
            });
        },
        _checkFormSel: function (newItem, allForms, data) {
            if (data) {
                $.each(data || [], function (id, item) {
                    if (item && newItem.id == id) {
                        newItem.sel = true;
                        newItem.buttons = item.buttons;
                        newItem.fieldControlId = item.fieldControlId;
                        return false;
                    }
                });
            } else {
                //新建节点初始化
                if (newItem.group) {
                    //判断是否有分组的情况,如果有则默认第一个选中
                    var groups = [];
                    $.each(allForms || [], function (id, item) {
                        if (item && item.group == newItem.group) {
                            groups.push(item);
                        }
                    });
                    $.each(groups, function (i, item) {
                        if (item && i == 0 && item.id == newItem.id) {
                            newItem.sel = true;
                        }
                    });
                } else {
                    newItem.sel = true;
                }
            }
        },
        _getFormTableCol: function (self, popWin, participant) {
            var formInfo = this.__Flowdesigner.curDrawLayer.forms;
            var title = this._getLang('table.nform.title');
            return [
                {
                    title: title[0],//'选择',
                    name: 'sel',
                    width: 50,
                    align: 'center',
                    lockWidth: true,
                    renderer: function (val, item, rowIndex) {
                        return '<div class="' + (val ? 'tableRowSelect' : 'tableRowNoSelect') + '"></div>';
                    }
                },
                {
                    title: title[1],//'表单名称',
                    name: 'name',
                    width: 170,
                    lockWidth: true
                },
                {
                    title: title[2],//'已选操作',
                    name: 'buttons',
                    width: 195,
                    renderer: function (val, item, rowIndex) {
                        if (item.id == 'FlowTrack' || !item.sel) {
                            return '';
                        }
                        var clientBtn = {};
                        var showTxt = val;
                        var form = formInfo[item.id];
                        if (form && form['buttons']) {
                            showTxt = '';
                            $.each(val.split(';') || [], function (i, value) {
                                if (value) {
                                    var label = form['buttons'][value];
                                    $.each(form['buttons'] || [], function (id, name) {
                                        if (id.indexOf('|') > 0) {
                                            if (id.split('|')[1] == value) {
                                                if (clientBtn[id.split('|')[0]]) {
                                                    clientBtn[id.split('|')[0]].push(name);
                                                } else {
                                                    clientBtn[id.split('|')[0]] = [name]
                                                }
                                                return false;
                                            }
                                        }
                                    });
                                }
                            });
                        }
                        var html = '';
                        Object.keys(clientBtn).sort().reverse().forEach(function (key) {

                            var clientName = 'pc端';
                            switch (key) {
                                case '1':
                                    clientName = '移动端';
                                    break;
                                case '2':
                                    clientName = '移动端';
                                    break;
                                case '3':
                                    clientName = '笔记本';
                                    break;
                                case '4':
                                    clientName = 'pc端';
                                    break;
                            }
                            html += '<span style="font-size: 12px;font-weight: 600;">' + clientName + '</span><br>';
                            html += '<span class="txtButs" style="padding-left: 12px;">';
                            $.each(clientBtn[key] || [], function (index, name) {
                                html += name + ';';
                            });
                            html += '</span><br>';
                        })
                        self._chgApplyBtn(popWin.find('#applyBtn'), false);
                        return html;
                    }
                },
                {
                    title: title[3],//'选择',
                    name: 'sel',
                    width: 75,
                    renderer: function (val, item, rowIndex) {
                        if (item.id == 'FlowTrack') {
                            return;
                        }
                        return '<button class="btn btn-info btn-sm selBtn">' + title[0] + '</button>';
                    }
                },
                {
                    title: title[4],//'分组',
                    name: 'group',
                    width: 60,
                    lockWidth: true
                },
                {
                    title: title[5],//'字段权限',
                    name: 'id',
                    width: 300,
                    renderer: function (val, item, rowIndex) {
                        if (item.id == 'FlowTrack') {
                            return;
                        }
                        var disable = false;
                        var form = formInfo[item.id];
                        if (!item.sel || item.fieldControlId == 'alleditable'
                            || item.fieldControlId == 'allreadonly') {
                            disable = true;
                        }
                        var options = '<option value="alleditable" ' +
                            ('alleditable' == item.fieldControlId ? 'selected' : '')
                            + '>' + title[7] + '</option>'
                            + '<option value="allreadonly" ' +
                            ('allreadonly' == item.fieldControlId ? 'selected' : '')
                            + '>' + title[8] + '</option>';

                        if (form && form['fieldControl']) {
                            $.each(form['fieldControl'] || [], function (id, data) {
                                if (data) {
                                    options += '<option value="' + id + '" ' +
                                        (id == item.fieldControlId ? 'selected' : '')
                                        + '>' + data.label + '</option>';
                                }
                            });
                        }
                        return '<select style="width:110px" class="checkChange fieldSel" '
                            + (!item.sel ? 'disabled' : '') + '>' + options + '</select>'
                            + '&nbsp;<button class="btn btn-info btn-sm fieldEdit" '
                            + (disable ? 'disabled' : '') + '>' + title[10] + '</button>'
                            + '&nbsp;<button class="btn btn-info btn-sm fieldAdd"'
                            + (!item.sel ? 'disabled' : '') + '>' + title[9] + '</button>'

                            ;
                    }
                },
                {
                    title: title[6],//'应用',
                    name: 'id',
                    width: 80,
                    align: 'center',
                    renderer: function (val, item, rowIndex) {
                        if (item.id == 'FlowTrack') {
                            return;
                        }
                        return '<button class="btn btn-info btn-sm fieldCopy">' + title[6] + '</button>';
                    }
                }
            ];
        },

        //弹出用于选择的窗口
        //编辑字段权限页面
        _editFieldPage: function (node, item, isAdd, callback) {
            var self = this;
            var html = self._getHtml('template/node/actionform/fieldEdit.html');
            var formId = item['id'];
            var formInfo = self.__Flowdesigner.curDrawLayer.forms;
            var fields = null;
            var field = {
                data: '',
                label: '',
                edit: '',    //可编辑
                must: '',    //必填
                read: '',    //只读
                hide: ''     //隐藏
                //其他为不输出
            };
            if (formInfo[formId]) {
                fields = formInfo[formId]['fields'];//表单所有字段
                if (!isAdd) {
                    field = formInfo[formId]['fieldControl'][item.fieldControlId];
                }
            } else {
                this._showMsg(this._getLang('table.nform.loaderr'));
                ('表单数据异常');
                return;
            }
            var tblObj = null;
            var tables = {};
            //为了弹出窗口中的input输入框能正常输入,需要先把模态窗口隐藏
            $('#hzPopModal').hide();
            //'[ '+item['name']+' ]字段权限设置'
            var title = this._getLang('prop.fieldset').replace('name', item['name']);
            this.__Flowdesigner.popSelWin(title, html,
                function ($this) {

                    // 保存成功后调用回调方法处理前端界面
                    //保存修改到数据库中,
                    var name = $this.find('input[name="authName"]').val();
                    if (!name) {
                        self._showMsg(self._getLang('table.nfield.iname'));//('请输入字段权限设置名称');
                        return false;
                    }
                    var checkRes = true;
                    self.__Flowdesigner.checkFormAuthNameToServer($this.find('input[name="authId"]').val(), $this.find('input[name="authName"]').val(), formId, function (data) {
                        if (data.restype == "err") {
                            checkRes = false;
                        }
                    })
                    if (!checkRes) {
                        self._showMsg(self._getLang('table.field.authRepeat'));
                        return false;
                    }
                    var result = {
                        formid: formId,
                        data: $this.find('input[name="authId"]').val(),
                        label: $this.find('input[name="authName"]').val(),
                        edit: '',
                        must: '',
                        read: '',
                        hide: ''
                    };
                    var tableKeys = Object.keys(tables);
                    for (var i = 0; i < tableKeys.length; i++) {
                        tblObj = tables[tableKeys[i]];
                        $.each(tblObj.rows() || [], function (i, item) {
                            if (!item) {
                                return true;
                            }
                            if (item.edit) {
                                result['edit'] += item.data + ';';
                                if (item.must) {
                                    result['must'] += item.data + ';';
                                }
                            } else if (item.read) {
                                result['read'] += item.data + ';';
                            } else if (item.hide) {
                                result['hide'] += item.data + ';';
                            }
                        });
                    }

                    var back = '';//saveFormFieldAuthToServer执行失败时
                    self.__Flowdesigner.saveFormFieldAuthToServer(result, function (data) {
                        if (data['result'] == 'ok') {
                            result['data'] = data['msg'];
                            back = 'ok';
                        } else {
                            back = data['msg'];
                        }
                    });
                    if (back != 'ok') { //saveFormFieldAuthToServer执行失败或者保存异常
                        if (back != '') {//保存异常信息输出
                            self._showMsg(back);
                        }
                        return false;
                    }

                    //增加到内存中
                    if (!formInfo[formId]['fieldControl']) {
                        formInfo[formId]['fieldControl'] = {};
                    }
                    formInfo[formId]['fieldControl'][result['data']] = result;

                    //更新下拉列表框(所有权限下的页签都需要更新)
                    $.each(node.operators || [], function (i, participant) {
                        var tblObj = self.tblObjArr[participant + '_nodeForm'];
                        tblObj.load(tblObj.rows());
                    })
                    if (callback) {
                        callback(result['data']);
                    }
                    $('#hzPopModal').show();
                    self._chgApplyBtn();
                    return true;

                },
                '680px', self._getLang('static.save'),
                function ($this) {
                    $this.$contentPane.css('max-height', '450px');
                    var items = [];
                    var isFirst = true;
                    var def = self._getLang('table.nfield.def');
                    var tableName = '';
                    var separator = '';
                    var formIds = [];
                    var clientFields = [];
                    var pcFields = [];
                    var notebookFields = [];
                    var padFields = [];
                    var phoneFields = [];
                    $.each(fields || [], function (data) {
                        var key = data, clientType;
                        if (key.indexOf('mixed_') == -1) {
                            if (data.split('|').length > 1) {
                                clientType = data.split('|')[0];
                                key = data.split('|')[1];
                            } else {
                                clientType = "4";
                                key = data;
                            }
                            switch (clientType) {
                                case "4":
                                    pcFields[key] = fields[data];
                                    break;
                                case "3":
                                    notebookFields[key] = fields[data];
                                    break;
                                case "2":
                                    padFields[key] = fields[data];
                                    break;
                                case "1":
                                    phoneFields[key] = fields[data];
                                    break;
                            }
                        }
                    })
                    if (Object.keys(pcFields).length > 0) clientFields['pc'] = pcFields;
                    if (Object.keys(notebookFields).length > 0) clientFields['notebook'] = notebookFields;
                    if (Object.keys(padFields).length > 0) clientFields['pad'] = padFields;
                    if (Object.keys(phoneFields).length > 0) clientFields['phone'] = phoneFields;
                    var clientFieldKeys = Object.keys(clientFields);
                    for (var i = 0; i < clientFieldKeys.length; i++) {
                        var client = clientFieldKeys[i];
                        var clientTypeFields = clientFields[client], items = [];
                        var clientTypeFieldKeys = Object.keys(clientTypeFields);
                        for (var j = 0; j < clientTypeFieldKeys.length; j++) {
                            var key = clientTypeFieldKeys[j];
                            var formId = key.split('_')[0];
                            if (formIds.indexOf(formId) == -1) {
                                formIds.push(formId);
                            }
                        }
                        if (field['edit'] || field['read'] || field['hide']) {
                            var authRule;
                            if (field['edit'] && field['edit'].indexOf(';') > -1) {
                                authRule = field['edit'].split(';')[0];
                            } else if (field['read'] && field['read'].indexOf(';') > -1) {
                                authRule = field['read'].split(';')[0];
                            } else if (field['hide'] && field['hide'].indexOf(';') > -1) {
                                authRule = field['hide'].split(';')[0];
                            }
                            if (authRule) {
                                //兼容旧版本
                                if (authRule.indexOf('&') > -1) {
                                    separator = '&';
                                } else if (authRule.indexOf('.') > -1) {
                                    separator = '.';
                                } else if ((authRule.indexOf('_') > -1 && formIds.indexOf(authRule.split('_')[0]) > -1)) {
                                    separator = '_';
                                }
                            }
                        }
                        isEx = function (list, fieldName) {
                            var item = list ? list.split(';') : [];
                            for (var i = 0; i < item.length; i++) {
                                if (item[i] === fieldName) {
                                    return true;
                                }
                            }
                            return false;
                        };
                        for (var j = 0; j < clientTypeFieldKeys.length; j++) {
                            var key = clientTypeFieldKeys[j];
                            var label = clientTypeFields[key];
                            var data = key;
                            if (label) {
                                var fieldName = data;
                                fieldName = data.substr(data.indexOf("_") + 1);
                                if (separator == '&') {
                                    tableName = label.split('&')[1];
                                    fieldName = tableName != '' ? tableName + separator + fieldName : fieldName;
                                } else if (separator == '.') {
                                    tableName = label.split('.')[0];
                                    fieldName = tableName != '' ? tableName + separator + fieldName : fieldName;
                                } else if (separator == '_') {
                                    fieldName = data;
                                } else if (separator == '') {
                                    fieldName = data.substr(data.indexOf('_') + 1);
                                }
                                items.push({
                                    data: data,
                                    label: label,
                                    // tabel: def,
                                    edit: isEx(field['edit'], fieldName),
                                    must: isEx(field['must'], fieldName),
                                    read: isEx(field['read'], fieldName),
                                    hide: isEx(field['hide'], fieldName)
                                });
                            }
                        }
                        $this.$content.find('.' + client).css('display', 'inline');
                        if (isFirst) {
                            $this.$content.find('.' + client).addClass('active');
                            $this.$content.find('#' + client).addClass('active');
                            isFirst = false;
                        }
                        tblObj = $this.$content.find('#' + client + '-popSel').mmGrid({
                            height: '184px'
                            ,delTitle:self._getLang('table.field.defTitle')
                            ,showCol:self._getLang('table.field.showCol')
                            ,delTitle:self._getLang('table.field.defTitle')
                            ,showCol:self._getLang('table.field.showCol')
                            , cols: self._selectFieldTableCol()
                            , items: items      //本地数据
                            , multiSelect: false
                            , fullWidthRows: true
                            , nowrap: false
                            , autoLoad: false
                            , loadingText: self._getLang('table.nfield.load')//'正在加载字段列表...'
                            , noDataText: self._getLang('table.nfield.nodata')//'当前无可选字段'
                        });
                        $('.authBox').on('click',function(){
                            var key = $(this).attr('name');
                            var static = $(this).is(":checked");
                            var $this =  $(this);
                            tblObj = tables[$this.parents('.tab-pane').attr('id')];
                            var items = tblObj.rows()
                            $.each(items, function (i, item) {
                                $.each(['edit', 'must', 'read', 'hide'], function (i, key) {
                                    item[key] = false;
                                });
                                $this.parents('.tab-pane').find('.authBox').prop('checked',false);
                                $this.prop('checked',static?'checked':false);
                                item[key] = static;
                                if(key == 'must'){
                                    item['edit'] = true;
                                    $this.parents('.tab-pane').find('.authBox[name="edit"]').prop('checked','checked');
                                }
                            });
                            tblObj.load(items);
                        })
                        tblObj
                            .on('cellSelected', function (e, item, rowIndex, colIndex) {
                                if (colIndex > 0) {
                                    var key = ['edit', 'must', 'read', 'hide'][colIndex - 1];
                                    item[key] = !item[key];
                                    if (item[key]) {
                                        self._chgFieldAuthClick(item, key);
                                        if (colIndex == 2) {
                                            item['edit'] = true;
                                        }
                                    } else if (colIndex == 1) {
                                        item['must'] = false;
                                    }
                                    tblObj = tables[$(this).parents('.tab-pane').attr('id')];
                                    tblObj.load(tblObj.rows());
                                }
                            })
                            .load();
                        tables[client] = tblObj;
                    }


                    //ID/Name
                    $this.$content.find('input[name="authId"]').val(field.data);
                    $this.$content.find('input[name="authName"]').val(field.label);

                    //事件绑定
                    $this.$content.find('input[name="applyTo"]').on('change', function () {
                        if (this.value != 'edit') {
                            $this.$content.find('input[name="must"]').prop('checked', false);
                        }
                        ;
                    });
                    $this.$content.find('input[name="must"]').on('change', function () {
                        if (this.checked) {
                            $this.$content.find('input[name="applyTo"][value="edit"]').prop('checked', true);
                        }
                    });
                    $this.$content.find('#btnApply').on('click', function () {
                        var must = $this.$content.find('input[name="must"]').prop('checked');
                        var sel = $this.$content.find('input[name="applyTo"]:checked').val();
                        var selFields = ''
                        $.each(tblObj.selectedRows() || [], function (i, item) {
                            if (!item) {
                                return true;
                            }
                            self._chgFieldAuthClick(item, sel, must);
                            selFields += item.data + ';';
                        });

                        tblObj.load(tblObj.rows());
                        tblObj.select(function (item, index) {
                            return selFields.indexOf(item.data) != -1;
                        });
                    });
                },
                true);

        },
        _chgFieldAuthClick: function (item, sel, must) {
            $.each(['edit', 'must', 'read', 'hide'], function (i, key) {
                item[key] = false;
            });
            if (must) {
                item.must = true;
                item.edit = true;
            } else {
                item[sel] = true;
            }
        },
        _selectFieldTableCol: function () {
            var title = this._getLang('table.nfield.title');
            return [
                // {
                //     title: title[0],//'标示',
                //     name: 'tabel',
                //     hidden: true
                // },
                {
                    title: title[1],//'字段名称',
                    name: 'label',
                    width: 255,
                    align: 'center',
                    renderer: function (val, item, rowIndex) {
                        var field = val.split("&");
                        return '<p title="' + field[0] + '">' + field[1] + '</p>';
                    }
                },
                {
                    titleHtml: '<input type="checkbox" class="authBox" name="edit"/><div style="display: inline-block;">&nbsp;' + title[2] + '</div>',//'编辑'
                    title: title[2],
                    name: 'edit',
                    width: 100,
                    align: 'center',
                    lockWidth: true,
                    renderer: function (val, item, rowIndex) {
                        return '<div class="' + (val ? 'tableRowSelect' : 'tableRowNoSelect') + '"></div>';
                    }
                },
                {
                    titleHtml: '<input type="checkbox" class="authBox" name="must"/><div style="display: inline-block;">&nbsp;' + title[3] + '</div>',//'必填',
                    title: title[3],
                    name: 'must',
                    width: 100,
                    align: 'center',
                    lockWidth: true,
                    renderer: function (val, item, rowIndex) {
                        return '<div class="' + (val ? 'tableRowSelect' : 'tableRowNoSelect') + '"></div>';
                    }
                },
                {
                    titleHtml: '<input type="checkbox" class="authBox" name="read"/><div style="display: inline-block;">&nbsp;' + title[4] + '</div>',//'只读',
                    title: title[4],
                    name: 'read',
                    width: 100,
                    align: 'center',
                    lockWidth: true,
                    renderer: function (val, item, rowIndex) {
                        return '<div class="' + (val ? 'tableRowSelect' : 'tableRowNoSelect') + '"></div>';
                    }
                },
                {
                    titleHtml: '<input type="checkbox" class="authBox" name="hide"/><div style="display: inline-block;">&nbsp;' + title[5] + '</div>',//'隐藏',
                    title: title[5],
                    name: 'hide',
                    width: 100,
                    align: 'center',
                    lockWidth: true,
                    renderer: function (val, item, rowIndex) {
                        return '<div class="' + (val ? 'tableRowSelect' : 'tableRowNoSelect') + '"></div>';
                    }
                }
            ];
        },
        //表单权限应用
        _selectFormApply: function (node, participant, sel, callback) {
            var self = this;
            var html = '<table id="popSel"/>';
            var selAll = self._getLang('prop.selall');
            html += '<table style="width:365px"><tr><td align="left">' +
                '<label className="checkbox-inline">' +
                '<input type="checkbox" name="selNode"/>' + selAll[0] + '</label>' +
                '</td><td align="right">' +
                '<label className="checkbox-inline">' +
                '<input type="checkbox" name="selForm" ' + (sel ? 'checked' : '') + '/>' + selAll[1] + '</label>' +
                '</td></tr></table>';
            var allNodes = this._sortFilterAllNode(node.__drawLayer._nodes,
                function (item) {
                    if (item.id == node.id) {
                        return false;
                    }
                    if (item.nodetype < 10 || item.nodetype == 900) {
                        return false;
                    }
                    //如果节点没有当前的页签,直接过滤掉
                    if (item.operators.indexOf(participant) == -1) {
                        return false;
                    }
                    return true;
                });
            $.each(allNodes || [], function (i, item) {
                if (item) {
                    item['selForm'] = sel; //默认选择此表单
                    item['sel'] = false;
                }
            });

            var tblObj = null;
            this.__Flowdesigner.popSelWin(self._getLang('static.selnode'), html,//'请选择节点'
                function ($this) {
                    callback(tblObj.rows());
                },
                '400px', null,
                function ($this) {
                    $this.$contentPane.css('max-height', '410px');
                    tblObj = $this.$content.find('#popSel').mmGrid({
                        height: 380
                        ,delTitle:self._getLang('table.field.defTitle')
                        ,showCol:self._getLang('table.field.showCol')
                        , cols: self._selectFormTableCol()
                        , items: allNodes      //本地数据

                        , multiSelect: false
                        , fullWidthRows: true
                        , autoLoad: false
                        , loadingText: self._getLang('table.selnode.load')//'正在加载节点列表...'
                        , noDataText: self._getLang('table.selnode.nodata')//'当前无可选节点'
                    });
                    tblObj
                        .on('cellSelected', function (e, item, rowIndex, colIndex) {
                            if (colIndex == 2) {
                                item.selForm = !item.selForm;
                                if (item.selForm) {
                                    //表单选中时,需要判断其他是否都为选中状态
                                    var allItem = tblObj.rows();
                                    var selForm = false;
                                    $.each(allItem || [], function (i, item) {
                                        if (item) {
                                            selForm = item.selForm;
                                            if (!selForm) {
                                                return false;//break;
                                            }
                                        }
                                    });
                                    if (selForm) {
                                        $this.$content.find('input[name="selForm"]').prop('checked', true);
                                    }
                                } else {
                                    $this.$content.find('input[name="selForm"]').prop('checked', false);
                                }
                            } else {
                                item.sel = !item.sel;
                                if (item.sel) {
                                    //节点选中时
                                    var allItem = tblObj.rows();
                                    var sel = false;
                                    $.each(allItem || [], function (i, item) {
                                        if (item) {
                                            sel = item.sel;
                                            if (!sel) {
                                                return false;//break;
                                            }
                                        }
                                    });
                                    if (sel) {
                                        $this.$content.find('input[name="selNode"]').prop('checked', true);
                                    }
                                } else {
                                    $this.$content.find('input[name="selNode"]').prop('checked', false);
                                }
                            }
                            tblObj.load(tblObj.rows());
                        })
                        .load();
                    $this.$content.find('input[name="selNode"]').on('change', function () {
                        var allItem = tblObj.rows();
                        var isCheck = $(this).is(':checked');
                        $.each(allItem || [], function (i, item) {
                            if (item) {
                                item.sel = isCheck;
                            }
                        });
                        tblObj.load(allItem);
                    });
                    $this.$content.find('input[name="selForm"]').on('change', function () {
                        var allItem = tblObj.rows();
                        var isCheck = $(this).is(':checked');
                        $.each(allItem || [], function (i, item) {
                            if (item) {
                                item.selForm = isCheck;
                            }
                        });
                        tblObj.load(allItem);
                    });

                });

        },
        _selectFormTableCol: function () {
            var title = this._getLang('table.selnode.title');
            return [
                {
                    title: title[0],//'选择',
                    name: 'sel',
                    width: 50,
                    align: 'center',
                    lockWidth: true,
                    renderer: function (val, item, rowIndex) {
                        return '<div class="' + (val ? 'tableRowSelect' : 'tableRowNoSelect') + '"></div>';
                    }
                },
                {
                    title: title[1],//'节点(ID)',
                    name: 'name',
                    width: 190,
                    align: 'center',
                    renderer: function (val, item, rowIndex) {
                        return val + '(' + item.id + ')';
                    }
                },
                {
                    title: title[2],//'选中此表单',
                    name: 'selForm',
                    width: 95,
                    align: 'center',
                    lockWidth: true,
                    renderer: function (val, item, rowIndex) {
                        return '<div class="' + (val ? 'tableRowSelect' : 'tableRowNoSelect') + '"></div>';
                    }
                }
            ];
        },
        //选择表单按钮
        _selectFormButton: function (allbuttons, selbuttons, callback) {
            var self = this;
            var html = '<select name="popSel" multiple style="width:100%;height:200px">';
            var clientTypes = [];
            var buttonsKeys = Object.keys(allbuttons).sort(function (a, b) {
                return b.split('|')[0] - a.split('|')[0];
            });
            $.each(buttonsKeys, function (index, key) {
                    var label = allbuttons[key];
                    if (!label) {
                        return true;
                    }
                    var id = key.split('|')[1];
                    var clientType = key.split('|')[0];
                    if (clientTypes.indexOf(clientType) < 0) {
                        var clientName = self._getLang('html.form.clientType.a1');
                        switch (clientType) {
                            case '1':
                                clientName = self._getLang('html.form.clientType.a2');
                                break;
                            case '2':
                                clientName = self._getLang('html.form.clientType.a2');
                                break;
                            case '3':
                                clientName = self._getLang('html.form.clientType.a1');
                                break;
                            case '4':
                                clientName = self._getLang('html.form.clientType.a1');
                                break;
                        }
                        clientTypes.push(clientType);
                        html += '<option value="" disabled="disabled" style=" font-size: 12px;font-weight: 600;padding-left: 0px;background-color: #f5f5f5;">' + clientName + '</option>';
                    }
                    if (selbuttons.indexOf(id) == -1) {
                        html += '<option value="' + id + '">' + label + '(' + id + ')</option>';
                    } else {
                        html += '<option value="' + id + '" selected>' + label + '(' + id + ')</option>';
                    }
                }
            );
            html += '</select>';
            this.__Flowdesigner.popSelWin(this._getLang('table.nform.selbtn'),//'请选择表单操作',
                html, function ($this) {
                    var selObj = $this.find('select[name="popSel"]');
                    callback(selObj.val());
                }, null, null, this._formButtonAuthSelect);
        },
        _formButtonAuthSelect: function (item) {
            (function () {
                item.$content.find("select")[0].onmousedown = function () {
                    var evt = event || window.event;
                    var selectObj = evt ? evt.srcElement : null;
                    if ($(selectObj).is('option') && selectObj.selected) {
                        item.$content.find("select").find($(selectObj)).prop("selected", '');
                        evt.preventDefault();
                    }
                }
            })();
        },
        //操作权限应用时选择节点/其他需要选中多个节点时/支持自定义过滤
        selectNodeMulti: function (node, callback, filterFun, defVal) {
            var html = '<select name="popSel" multiple style="width:100%;height:200px">';
            var allNodes = this._sortFilterAllNode(node.__drawLayer._nodes,
                function (item) {
                    if (item.id == node.id) {
                        return false;
                    }
                    if (item.nodetype < 10 || item.nodetype == 900) {
                        return false;
                    }
                    if (filterFun) {
                        return filterFun(item);
                    }
                    return true;
                });
            $.each(allNodes || [], function (i, item) {
                if (!item) {
                    return true;
                }
                var sel = ''
                if (defVal && defVal.indexOf(item.id + ';') != -1) {
                    sel = 'selected';
                }
                html += '<option value="' + item.id + '"' + sel + '>' + item.name + '(' + item.id + ')</option>';
            });
            html += '</select>';
            this.__Flowdesigner.popSelWin(this._getLang('table.action.selnode'),//'请选择节点(多选)',
                html,
                function ($this) {
                    var selObj = $this.find('select[name="popSel"]');
                    callback(selObj);
                });
        }
        ,

//选择有办理人的节点,支持单选多选,自定义过滤,单选可以再次点击取消选择
        _selectNodeAndBack: function (node, callback, multi, sel, filterFun) {
            var self = this;
            var multi = multi || false;
            var html = '<select name="popSel" ' + (multi ? 'multiple' : 'size ="10"') +
                ' style="width:100%;height:200px" title="' + self._getLang('prop.tooltip') + '">';
            var allNodes = this._sortFilterAllNode(node.__drawLayer._nodes,
                function (item) {
                    if ((item.nodetype >= 10 && item.nodetype < 40) || item.nodetype == 50) {
                        if (filterFun) {
                            return filterFun(item);
                        }
                        return true;
                    }
                    return false;
                });

            $.each(allNodes || [], function (i, item) {
                if (!item) {
                    return true;
                }
                var select = sel && sel.indexOf(item.id + ';') != -1 ? 'selected' : '';
                html += '<option value="' + item.id + '" ' + select + '>' + item.name + '(' + item.id + ')</option>';
            });
            html += '</select>';
            this.__Flowdesigner.popSelWin(self._getLang('prop.selnode_user'),//'请选择节点(有办理人的节点)',
                html,
                function ($this) {
                    var selObj = $this.find('select[name="popSel"]');
                    var allsel = multi ? selObj.val() : [selObj.val()];
                    var data = [];
                    $.each(allsel || [], function (i, id) {
                        if (id) {
                            var option = selObj.find('option[value="' + id + '"]');
                            data.push({data: id, label: option.text()});
                        }
                    });
                    callback(data);
                },
                null, null,
                function ($this) {
                    //if (!multi)
                    {
                        $this.$content.find('select[name="popSel"] option').on('mousedown', function () {
                            var pVal = $(this).parent().val();
                            var tVal = this.value;
                            if (pVal && pVal == tVal) {
                                $(this).on('mouseup', function () {
                                    $(this).prop('selected', false);
                                    $(this).off('mouseup');
                                });
                            }
                        });
                    }
                });
        }
        ,

//选择子流程
        _selectSubflow: function (tblNodeSubflow) {
            var self = this;
            this.__Flowdesigner.openWinForSelFlow(function (flowid, flowname) {
                //判断选择的流程是否已经在列表中
                var isHave = false;
                $.each(tblNodeSubflow.rows() || [], function (i, item) {
                    if (item && item.id == flowid) {
                        isHave = true;
                        return false;
                    }
                });
                if (isHave) {
                    self._showMsg(self._getLang('prop.subexist'));//('所选流程已在列表中');
                    return false;
                } else {
                    tblNodeSubflow.addRow({
                        id: flowid,
                        name: flowname
                    });
                    self._chgApplyBtn();
                }
            });
        }
        ,

//----------数据更新--------------------
        _applyPropertiesData: function (popWin, node) {
            var data = {};
            data.id = node.id;
            //都需要的判断放在这里
            data.name = popWin.find('input[name="nodeName"]').val();
            if (!data.name || data.name.trim() == '') {
                return this._getLang('prop.inodename');//'请输入节点名称';
            }
            if (data.name.length > 30) {
                return this._getLang('msg.tooLong.nodeName');//'节点名称不能超过30个字符';
            }
            var nxtSelType = popWin.find(':radio[name="nxtSelType"]:checked').val();
            if (!nxtSelType) {
                nxtSelType = '2';
            }
            nxtSelType = parseInt(nxtSelType);
            if (isNaN(nxtSelType)) {
                return this._getLang('prop.nodeseltype');//'请选择后续分支类型';
            }
            data.nxtSelType = nxtSelType;

            var nodeType = parseInt(popWin.find('select[name="nodeType"]').val());
            if (isNaN(nodeType)) {
                return this._getLang('prop.ntypenull');//'节点类型为空';
            }
            data.nodeType = nodeType;

            data.className = popWin.find('input[name="className"]').val();
            if (!data.className && nodeType != 210) {
                return this._getLang('prop.nclassnull');//'节点实现类必须要指定';
            }
            data.memo = popWin.find('textarea[name="memo"]').val();

            //参与者
            data['participants'] = {};
            var result = this._applyParticipant(popWin, node, data);
            if (result) {
                return result;
            }
            //操作
            data['authDo'] = {};
            this._applyOperator(popWin, node, data);
            //事件列表
            data['events'] = {};
            var events = this._applyTable(popWin, 'tblNodeEvent', 'type');
            if (events) {
                data['events'] = events;
            }
            //异常列表
            data['exceptions'] = {};
            var exceptions = this._applyTable(popWin, 'tblNodeException', 'code');
            if (exceptions) {
                data['exceptions'] = exceptions;
            }
            //节点参数列表
            data['paras'] = {};
            var paras = this._applyTable(popWin, 'tblNodePara', 'id');
            if (paras) {
                data['paras'] = paras;
            }
            //子流程列表
            data['subflow'] = {};
            var flows = this._applyTable(popWin, 'tblNodeSubflow', 'id');
            if (flows) {
                $.each(flows || [], function (key, flow) {
                    if (!flow) {
                        return true;
                    }
                    delete flow['vars'];
                    $.each(flow['paras'] || [], function (i, para) {
                        if (para) {
                            delete para['vars'];
                        }
                    });

                });
                //清空子流程变量信息
                data['subflow']['flows'] = flows;
                data['subflow']['wait'] = popWin.find('input[name="wait"]').prop('checked') ? 1 : 0;
                data['subflow']['multi'] = popWin.find('input[name="multi"]').prop('checked') ? 1 : 0;
            }
            if (data['authDo']['Author']) {
                var subflowActionid = node._getOptions('subflow');
                var subflowActionName = node._getOptions('operators.' + subflowActionid + '.name');
                var reg = /name/g;
                var buttons = data['authDo']['Author']['buttons']['actions'];
                if (flows == null) {
                    flows = [];
                }
                if (Object.keys(flows).length > 0 && !buttons[subflowActionid]) {
                    //如果没有启动子流程,但是设置了子流程则提示
                    buttons[subflowActionid] = this._applySubflowAction(true);
                    this._showMsg(this._getLang('static.addsub').replace(reg, subflowActionName));
                } else if (Object.keys(flows).length == 0 && buttons[subflowActionid]) {
                    this._applySubflowAction(false);
                    delete buttons[subflowActionid];
                    //没有子流程但是有启动子流程操作
                    this._showMsg(this._getLang('static.delsub').replace(reg, subflowActionName));
                }
            }
            //不同节点需要判断的放在各自的类
            result = node.applyPropertiesData(popWin, data);

            if (result) {
                return result;
            } else {
                //相关数据的更新处理
                if (node.name != data.name) {
                    node.name = data.name;
                    node._setName();
                    //还需要更新相关的地方
                    //路由上的节点名称,和map中的节点名称
                    var nodeid = node.id;
                    //指向节点的路由名称修改
                    $.each(node.__drawLayer._routes || [], function (i, line) {
                        if (line && line.toNode.id == nodeid) {
                            line.fromNode.data['transitions'][line.id]['nodeName'] = node.name;
                        }
                    });
                    //map的名称修改
                    node.map['name'] = node.name;
                }

                //需要把节点上的路由信息复制到新的data上,否则会丢失
                data['transitions'] = node.data['transitions'];

                node.data = data;
                node.nodetype = data.nodeType;
                node.__drawLayer.data['process'][node.id] = node.data;
                //map中的节点类型也需要修改
                node.map['nodeType'] = data.nodeType;

                //处理子流程节点的map数据
                node.doSubflow();
                //同一类节点的类型变化时,图片修改
                node.chgNodeShapeForTest('defurl');


                var title = this._getLang('prop.title')
                    .replace('name', data.name)
                    .replace('id', data.id);
                popWin.find('#hzPopModalLabel').html(title);
                return '';
            }
        }
        ,
        _applyParticipant: function (popWin, node, data) {
            var self = this;
            var result = '';
            $.each(node.participants || [], function (i, participant) {
                var newParticipant = FlowInit.initAuth();
                newParticipant['authId'] = participant;
                newParticipant['authName'] = self.options.participantsName[participant];
                var control = '';
                var controlObj = popWin.find('#p' + participant + '_control');
                $.each(controlObj.find('input[name="control"]') || [], function () {
                    if (this.checked) {
                        control += ';' + this.value;
                    }
                });
                if (control.indexOf('PassNodeUser') != -1) {
                    var passNode = controlObj.find('input[name="passNode"]');
                    if (!passNode.val()) {
                        result = self._getLang('prop.jumpuser');//('跳过指定节点办理人时,需要指定节点');
                        return false;
                    }
                    newParticipant['passNode'] = passNode.attr('data');
                }
                if (control.indexOf('FreeSelect') != -1) {
                    var sel = '';
                    $.each(controlObj.find('input[name="selectArea"]') || [], function () {
                        if (this.checked) {
                            sel += ';' + this.value;
                        }
                    });
                    newParticipant['select'] = sel ? sel.substring(1) : '';
                }

                newParticipant['control'] = control ? control.substring(1) : '';
                var sendMsg = '';
                $.each(popWin.find('#p' + participant + '_sendMsg').find('input[name="sendMsg"]') || [],
                    function () {
                        if (this.checked) {
                            sendMsg += ';' + this.value;
                        }
                    });
                newParticipant['msgFlag'] = sendMsg ? sendMsg.substring(1) : '';

                //组织
                $.each(self.tblObjArr[participant + '_userOrg'].rows() || [], function (i, item) {
                    if (item) {
                        newParticipant[item.type] += item.data + ';';
                    }
                });
                //字段
                $.each(self.tblObjArr[participant + '_userField'].rows() || [], function (i, item) {
                    if (item) {
                        newParticipant['formField']['name'] += item.data + ';';
                        newParticipant['formField']['pageId'] += item.pageId + ';';
                    }
                });
                //变量
                $.each(self.tblObjArr[participant + '_userVar'].rows() || [], function (i, item) {
                    if (item) {
                        if (item.sel) {
                            newParticipant['flowVar']['name'] += item.varId + ';';
                        }
                    }
                });
                //相对关系
                $.each(self.tblObjArr[participant + '_userRelation'].rows() || [], function (i, item) {
                    if (item) {
                        newParticipant['relation'].push(item);
                    }
                });
                //规则
                var userRule = popWin.find('#p' + participant + '_userRule');
                newParticipant['rule']['id'] = userRule.find('input[name="userRuleId"]').val();
                newParticipant['rule']['script'] = userRule.find('textarea[name="userRuleScript"]').val();
                newParticipant['rule']['text'] = userRule.find('textarea[name="userRuleText"]').val();

                var userCustomer = popWin.find('#p' + participant + '_userCustomer');
                newParticipant['customer']['check'] = userCustomer.find('input[name="customerCheck"]').prop('checked') ? 1 : 0;
                newParticipant['customer']['memo'] = userCustomer.find('textarea[name="customerMemo"]').val();
                newParticipant['customer']['className'] = userCustomer.find('.customerClass').val();
                newParticipant['customer']['classId'] = userCustomer.find('select[name="customClassSelect"]').val();

                data.participants[participant] = newParticipant;
            });

            return result;
        }
        ,
        _applyOperator: function (popWin, node, data) {
            var self = this;
            var result = '';
            var allForms = node.__drawLayer.data.flowInfo['forms'];//所有已经定义的表单列表
            $.each(node.operators || [], function (i, participant) {
                var newOperator = FlowInit.initDo();
                newOperator['id'] = participant;
                //操作
                self._applyOperatorAction(popWin, participant, newOperator['buttons'], data);

                //表单
                self._applyOperatorForm(popWin, participant, newOperator['forms'], allForms);

                data.authDo[participant] = newOperator;
            });

            return result
        }
        ,
//强制对启动子流程按钮进行选中或者取消
        _applySubflowAction: function (selSub) {
            var self = this;
            var actionKey = 'Author_nodeAction';
            var allRows = this.tblObjArr[actionKey].rows();
            var button = {};
            $.each(allRows || [], function (i, item) {
                if (item && item.id == 'subflow') {
                    item.sel = selSub;
                    self.tblObjArr[actionKey].load(allRows); //刷新表数据显示，在应用时需要同步显示刷新
                    button = {
                        id: item.id,
                        name: item.name,
                        reName: item.reName,
                        implClass: item.implClass
                    };
                    return self.__Flowdesigner.BREAK;
                }
            });
            return button;
        }
        ,
        _applyOperatorAction: function (popWin, participant, buttons, data) {
            var actionKey = participant + '_nodeAction';
            var actionObj = popWin.find('#o' + actionKey);
            if (participant == 'Author') {
                data['rejectOther'] =
                    actionObj.find('input[name="rejectOther"]').prop('checked') ? '1' : '0';

                var rejectNode = actionObj.find('select[name="rejectNodes"]');//.attr('data');
                buttons['rejectNodes'] = this._getSelAllOptionsVal(rejectNode);
            } else if (participant == 'Done') {
                var backNode = actionObj.find('select[name="backNodes"]');//.attr('data');
                buttons['backNodes'] = this._getSelAllOptionsVal(backNode);
            }

            var allRows = this.tblObjArr[actionKey].rows();
            var actions = {};
            $.each(allRows || [], function (i, item) {
                if (item && item.sel) {
                    item.reName = actionObj.find('input[name="reName_' + i + '"]').val();
                    actions[item.id] = {
                        id: item.id,
                        name: item.name,
                        reName: item.reName,
                        implClass: item.implClass
                    };
                }
            });
            buttons['actions'] = actions;
        }
        ,
        _applyOperatorForm: function (popWin, participant, forms, allForms) {
            var fd = this.__Flowdesigner;
            var formKey = participant + '_nodeForm';
            var formObj = popWin.find('#o' + formKey);
            forms['dfId'] = formObj.find('select[name="defForm"]').val();
            forms['chg'] = formObj.find('input[name="chgForm"]').prop('checked') ? 1 : 0;
            var allRows = this.tblObjArr[formKey].rows();
            var newForms = {};
            var num1 = 0, num2 = 0;
            $.each(allRows || [], function (i, item) {
                if (item && item.sel) {
                    newForms[item.id] = {
                        id: item.id,
                        buttons: item.buttons,
                        sort: num1++,
                        fieldControlId: item.fieldControlId
                    };
                }
            });
            forms['form'] = newForms;
            if (forms['chg'] != 1) {
                //恢复顺序
                var sortForms = {};
                $.each(allForms, function (id, flowform) {
                    $.each(newForms, function (key, form) {
                        if (flowform.id == form.id) {
                            form.sort = num2++;
                            sortForms[form.id] = form;
                            return fd.BREAK;
                        }
                    });
                    if (num1 == num2) {
                        return fd.BREAK;
                    }
                });
                forms['form'] = sortForms;
            }

        }
        ,
        _applyTable: function (popWin, tbl, key) {
            var table = popWin.find('#' + tbl);
            if (table.length == 0) {
                return null;
            }
            var allEvent = this.tblObjArr[tbl].rows();
            var data = {};
            // data[name]= {};
            $.each(allEvent || [], function (i, item) {
                if (item) {
                    data[item[key]] = item;
                }
            });
            return data;
        }

    }
    ;

    return NodeProperties;
})
;

define('flowdesigner/element/properties/LineProperties',['require','jquery'],function (require) {
    var $ = require('jquery');

    var LineProperties = function (opts, fd) {
        this.options = opts;
        this.__Flowdesigner = fd;
    };

    LineProperties.prototype = {
        constructor: LineProperties,
        tblObjArr: null,
        _getLang: function (key) {
            return this.__Flowdesigner.getLang(key);
        },
        _getHtml: function (key) {
            return this.__Flowdesigner.getHtml(key);
        },
        _showMsg: function (msg, title, callback) {
            this.__Flowdesigner.showMsg(msg, title, callback);
        },
        _chgApplyBtn: function (applyBtn, disabled) {
            this.__Flowdesigner._chgApplyBtn(applyBtn, disabled);
        },
        showProperties: function (line) {
            var self = this;
            var data = line.data;
            if (!data) {
                this._showMsg('Router Data is null.');
                return;
            }
            var popHtml = $(self._getHtml('template/router.html'));
            popHtml.find('#base').html(self._getHtml('template/router/base.html'));

            var html = "";
            if (line.fromNode.nodetype == 900) {//虚拟节点
                html = '<li role="presentation">' +
                    '    <a href="#scope" aria-controls="scope" role="tab" data-toggle="tab">' +
                    self._getLang('html.router.scope.title')
                    + '</a></li>';
                popHtml.find('#scope').html(self._getHtml('template/router/scope.html'));
            } else {
                html = '<li role="presentation">' +
                    '    <a href="#condition" aria-controls="condition" role="tab" data-toggle="tab">' +
                    self._getLang('html.router.condition.title')
                    + '</a></li>';
                popHtml.find('#condition').html(self._getHtml('template/router/condition.html'));
            }
            popHtml.find('#navTabs').append(html);

            var title = this._getLang('prop.title')
                .replace('name', data.name)
                .replace('id', data.id);
            this.__Flowdesigner.showPopWin({
                title: title,
                popHtml: popHtml,
                data: line,
                width: '950px',
                height: '435px',
                initFun: function (popWin, line) {
                    return self._initPropertiesData(popWin, line);
                },
                applyFun: function (popWin, line) {
                    return self._applyPropertiesData(popWin, line);
                }
            });

            $('#applyBtn').attr('disabled', true);
        },
        _initPropertiesData: function (popWin, line) {
            var self = this;
            var data = line.data;
            popWin.find('input[name="routerId"]').val(data.id);
            popWin.find('input[name="routerName"]').val(data.name);
            popWin.find('input[name="routerSort"]').val(data.sort);
            popWin.find('textarea[name="memo"]').val(data.memo);
            popWin.find('textarea[name="condition"]').on('keyup', function () {
                line.data['condition'] = popWin.find('textarea[name="condition"]').val();
            });
            popWin.find('textarea[name="condition"]').on('paste', function () {
                line.data['condition'] = popWin.find('textarea[name="condition"]').val();
            });
            if (line.fromNode.nodetype == 900) {
                var allNodes = popWin.find('select[name="allNodes"]');
                var executions = popWin.find('select[name="executions"]');
                var includes = popWin.find('select[name="includes"]');
                var eNodes = data['executions'] || '';
                var iNodes = data['includes'] || '';
                $.each(line.__drawLayer._nodes || [], function (i, node) {
                    if (node) {
                        var nodetype = node.nodetype;
                        if ((nodetype >= 100 && nodetype != 210) || nodetype < 10 || line.toNode.id == node.id) {
                            return true;
                        }
                        if (iNodes.indexOf(node.id + ';') != -1) {
                            includes.append('<option value="' + node.id + '">' + node.name + '</option>');
                        } else if (eNodes.indexOf(node.id + ';') != -1) {
                            executions.append('<option value="' + node.id + '">' + node.name + '</option>');
                        } else {
                            allNodes.append('<option value="' + node.id + '">' + node.name + '</option>');
                        }
                    }
                });

                executions.on('dblclick', function () {
                    self._moveOption(popWin, executions, allNodes);
                });
                includes.on('dblclick', function () {
                    self._moveOption(popWin, includes, allNodes);
                });
                popWin.find('#btnLeftAdd').on('click', function () {
                    self._moveOption(popWin, allNodes, includes);
                });
                popWin.find('#btnLeftDel').on('click', function () {
                    self._moveOption(popWin, includes, allNodes);
                });
                popWin.find('#btnRightAdd').on('click', function () {
                    self._moveOption(popWin, allNodes, executions);
                });
                popWin.find('#btnRightDel').on('click', function () {
                    self._moveOption(popWin, executions, allNodes);
                });
            } else {
                //获取参数列表
                var vars = line.__drawLayer.data.flowInfo['vars'];
                var conVar = popWin.find('select[name="conVar"]');
                $.each(vars || [], function (key, item) {
                    if (!item) {
                        return true;
                    }
                    conVar.append('<option value="' + item.varId + '" type="' + item.varType + '">'
                        + item.varName + '</option>');
                });
                conVar.on('change', function () {
                    self._chgVarSel(popWin, $(this));
                });
                conVar.change();
                popWin.find('#btnAddCondition').on('click', function () {
                    self._addCondition(popWin);
                });
                popWin.find('#btnDelCondition').on('click', function () {
                    self._delCondition(popWin, false);
                });
                popWin.find('#btnDelAllCondition').on('click', function () {
                    self._delCondition(popWin, true);
                });
                popWin.find('#btnInsertCondition').on('click', function () {
                    self._insertCondition(popWin);
                });
                popWin.find('#btnChgCondition').on('click', function () {
                    self._chgConditionShow(popWin);
                });
                popWin.find('#btnEditCondition').on('click', function () {
                    self._EditCondition(popWin);
                });
                //用于显示的内容
                //popWin.find('textarea[name="conditionCn"]').val(data['conditionCn']);
                var table = popWin.find('#tblCondition');
                var title = self._getLang('html.router.condition.table.title');
                var items = null;
                // if (data['conditionCn'] && data['conditionCn'][0]) {
                //     items = data['conditionCn'];
                // }
                //用于计算的内容
                popWin.find('textarea[name="condition"]').val(data['condition']);
                //默认隐藏
                // popWin.find('textarea[name="condition"]').hide();
                //满足下面条件时显示
                if (!items && data['condition']) {
                    popWin.find('textarea[name="condition"]').show();
                    table.hide();
                }

                var tblCondition = table.mmGrid({
                    height: 185
                    ,delTitle:self._getLang('table.field.defTitle')
                    ,showCol:self._getLang('table.field.showCol')
                    , cols: self._getConditionTableCol(title)
                    , items: items      //本地数据

                    , multiSelect: false
                    , fullWidthRows: true
                    , autoLoad: false
                    , loadingText: self._getLang('html.router.condition.table.load')//'正在加载异常列表...'
                    , noDataText: self._getLang('html.router.condition.table.nodata')//'请添加异常'
                });
                tblCondition
                    .on('cellSelected', function (e, item, rowIndex, colIndex) {
                        //判断当前数据是否被选中
                        var selectIndex = tblCondition.selectedRowsIndex();
                        if (selectIndex[0] == rowIndex) {
                            //取消选中
                            self._initConditionSel(popWin, null);
                            popWin.find('#btnAddCondition').text(self._getLang('prop.add'));//('添加');
                        } else if (popWin.find('#btnAddCondition').text() == self._getLang('prop.apply')) {
                            self._initConditionSel(popWin, item);
                            popWin.find('#btnAddCondition').text(self._getLang('prop.apply'));//('应用');
                        }
                    }).load();

                //记录表格对象,为确认保存数据使用
                self.tblObjArr = tblCondition;

                var tmpRule = {         //路由条件扩展判断时需要的实现类或者是规则脚本
                    id: '',     //规则id(用于存储规则信息的数据id)
                    text: '',   //规则显示时的内容
                    rule: '',   //规则可以执行的脚本内容
                    className: ''//路由条件扩展判断时的实现类,跟规则互斥
                    //className不为空时,id,text,rule无效
                };
                this.__Flowdesigner.bindRuleOrClass(null, popWin, 'router', data['rule'] || tmpRule);
            }

            //示例代码
            popWin.find('.btnExample').on('click', function () {
                self.__Flowdesigner.showExampleJava();
            });

            return "";
        },
        _chgConditionShow: function (popWin) {
            // if(popWin.find('textarea[name="condition"]');
            var show = true;
            show = popWin.find('.mmGrid').is(":visible");
            if (show) {
                popWin.find('.mmGrid').hide();
                popWin.find('textarea[name="condition"]').val(this._getAllCondition());
                popWin.find('textarea[name="condition"]').show();
            } else {
                popWin.find('.mmGrid').show();
                popWin.find('textarea[name="condition"]').hide();
            }

        },
        _getConditionTableCol: function (title) {
            var self = this;
            return [
                {
                    title: title[0],//关系
                    name: 'cTypeName',
                    width: 43,
                    lockWidth: true,
                    renderer: function (val, item, rowIndex) {
                        if (rowIndex == 0) {
                            return '';
                        }
                        return val;
                    }
                },
                {
                    title: title[1],//左括号
                    name: 'leftBrackets',
                    width: 40,
                    lockWidth: true
                },
                {
                    title: title[2],//变量名称
                    name: 'varName',
                    width: 200,
                    lockWidth: true
                },
                {
                    title: title[3],//对比
                    name: 'operatorName',
                    width: 70,
                    lockWidth: true
                },
                {
                    title: title[4],//值
                    name: 'cTxt',
                    width: 205,
                    lockWidth: true
                },
                {
                    title: title[5],//右括号
                    name: 'rightBrackets',
                    width: 40,
                    lockWidth: true
                }
            ]
        },
        _moveOption: function (popWin, fromSel, toSel) {
            $.each(fromSel.val() || [], function (i, id) {
                if (!id) {
                    return true;
                }
                var option = fromSel.find('option[value="' + id + '"]');
                //添加到includes中
                toSel.append('<option value="' + id + '">' + option.text() + '</option>');
                //从allNodes中删除
                option.remove();
            });
            this._chgApplyBtn(popWin.find('#applyBtn'), false);
        },
        _chgVarSel: function (popWin, $this) {
            //conOperator初始化
            if (!$this.val()) {
                return;
            }
            var conOperator = popWin.find('select[name="conOperator"]');
            conOperator.empty();

            var option = $this.find("option:selected");
            var varType = option.attr('type');
            switch (varType) {
                case '1':
                case '6':
                    $.each(this.options.operatorListCon, function (i, item) {
                        conOperator.append('<option value="' + item.data + '">' + item.label + '</option>')
                    });
                case '3':
                    $.each(this.options.operatorListStr, function (i, item) {
                        conOperator.append('<option value="' + item.data + '">' + item.label + '</option>')
                    });
                    break;
                default:
                    $.each(this.options.operatorListNum, function (i, item) {
                        conOperator.append('<option value="' + item.data + '">' + item.label + '</option>')
                    });
            }

            //TODO 流程条件,变量对比值的输入,是否需要根据类型弹出选择框呢??

            // if(varType == '4' || varType == '5'){
            //     //日期选择???
            // }
            // else{
            // }

        },
        _initConditionSel: function (popWin, item) {
            if (item) {
                var conVar = popWin.find('select[name="conVar"]');
                conVar.val(item['varId']);
                conVar.change();
                var conOperator = popWin.find('select[name="conOperator"]');
                conOperator.val(item['operatorId']);

                popWin.find('input[name="conTxt"]').val(item['cTxt']);
                popWin.find('input[name="leftBrackets"]').val(item.leftBrackets);
                popWin.find('input[name="rightBrackets"]').val(item.rightBrackets);
                if (item['cType']) {
                    popWin.find('select[name="conType"]').val(item['cType']);
                }
            } else {
                popWin.find('input[name="conTxt"]').val('');
            }
        },
        _delCondition: function (popWin, delAll) {
            var self = this;
            //var condition= popWin.find('textarea[name="condition"]');

            if (!delAll && self.__Flowdesigner.delCheckSel(self.tblObjArr)) {
                return;
            }
            self.__Flowdesigner.applyQuestion(self._getLang(delAll ? 'html.router.condition.table.delAll' : 'html.router.condition.table.del'),
                function () {
                    if (delAll) {
                        self.tblObjArr.removeRow();
                    } else {
                        self.tblObjArr.removeRow(self.tblObjArr.selectedRowsIndex());
                        var rows = self.tblObjArr.rows();
                        if (rows[0]) {
                            self.tblObjArr.load(self.tblObjArr.rows());
                        }
                    }
                    popWin.find('textarea[name="condition"]').val('');
                    self._chgApplyBtn(popWin.find('#applyBtn'), false);
                });


        },

        _EditCondition: function (popWin) {
            var selectIndex = this.tblObjArr.selectedRowsIndex();
            if (selectIndex.length == 1) {
                var item = this.tblObjArr.selectedRows()[0];
                this._initConditionSel(popWin, item);
                popWin.find('#btnAddCondition').text(this._getLang('prop.apply'));//('应用');
            } else {
                this._showMsg(this._getLang('html.router.condition.table.edit'));
            }
        },
        _addCondition: function (popWin) {
            var item = this._makeConditionItem(popWin);
            if (!item) {
                return;
            }
            var condition = popWin.find('textarea[name="condition"]').val();
            if (condition != "") {
                condition += item.cType;
            }
            condition += item.condition;
            popWin.find('textarea[name="condition"]').val(condition);
            // var selIndex = this.tblObjArr.selectedRowsIndex();
            //
            // var btnName = popWin.find('#btnAddCondition').text();//.text(this._getLang('prop.apply'));//('应用');
            // if(btnName == this._getLang('prop.apply')){
            //     if(selIndex.length ==1){
            //         this.tblObjArr.updateRow(item,selIndex[0]);
            //         popWin.find('#btnAddCondition').text(this._getLang('prop.add'));//('添加');
            //     }
            // }
            // else{
            //     this.tblObjArr.addRow(item);
            // }
            //
            popWin.find('input[name="conTxt"]').val('');
            this._chgApplyBtn(popWin.find('#applyBtn'), false);
        },
        _insertCondition: function (popWin) {
            var selIndex = this.tblObjArr.selectedRowsIndex();
            if (selIndex.length == 1) {
                var btnName = popWin.find('#btnAddCondition').text();
                if (btnName == this._getLang('prop.apply')) {
                    this._showMsg(this._getLang('html.router.condition.table.editinsert'));
                    return;
                }


                var item = this._makeConditionItem(popWin);
                if (!item) {
                    return;
                }
                this.tblObjArr.addRow(item, selIndex[0]);
                this.tblObjArr.load(this.tblObjArr.rows());
                popWin.find('input[name="conTxt"]').val('');
            } else {
                this._showMsg(this._getLang('html.router.condition.table.insert'));
                return;
            }

            this._chgApplyBtn(popWin.find('#applyBtn'), false);
        },
        _makeConditionItem: function (popWin) {
            var item = {};
            var conVar = popWin.find('select[name="conVar"]');
            var conVarVal = conVar.val();
            item['varId'] = conVarVal;  //变量ID
            if (!conVarVal) {
                this._showMsg(this._getLang('prop.selvar'));//'请选择参数'
                return;
            }
            var conTxt = popWin.find('input[name="conTxt"]').val();
            item['cTxt'] = conTxt;      //值
            if (conTxt == '') {
                this._showMsg(this._getLang('prop.inputcon'));//请输入判断内容
                return;
            }
            //判断方式
            var conObj = popWin.find('select[name="conOperator"]');
            var con = conObj.val();
            //判断方式名称
            var conCn = conObj.find("option:selected").text();
            item['operatorId'] = con;       //比较ID
            item['operatorName'] = conCn;   //比较中文
            //参数名称
            var conVarCn = conVar.find("option:selected").text();
            item['varName'] = conVarCn;     //变量名称


            var tmpStr = '';
            var varType = conVar.find("option:selected").attr('type');
            if (varType == '1' || varType == '6') {//字符
                if (con == '==' || con == '!=') {
                    tmpStr = '(' + (con == '==' ? '' : '!') + conVarVal + '.equals("' + conTxt + '"))';
                } else if (con == 'in' || con == 'noIn') {
                    tmpStr = '(' + conVarVal + '.indexOf("' + conTxt + '")' + (con == 'in' ? '!=' : '==') + '-1)';
                }
            } else if (varType == '2' || varType == '3' || varType == '7') {//数字和布尔
                tmpStr = "(" + conVarVal + con + conTxt + ")";
            } else if (varType == '4') {//日期
                if (conTxt.length != 10) {
                    this._showMsg(this._getLang('prop.dateErr1')); //输入的日期格式不正确(参考:2019-06-14)
                    return;
                }
                // conTxt = dateTimeFormatter.format(conTxt);
                tmpStr = '(' + conVarVal + con + 'df.parse("' + conTxt + '").getTime())';
            } else if (varType == '5') {	//日期时间
                if (conTxt.length == 10 || conTxt.length == 19) {
                    // conTxt = dateTimeFormatter.format(conTxt);
                    tmpStr = '(' + conVarVal + con + 'df.parse("' + conTxt + '").getTime())';
                } else {
                    this._showMsg(this._getLang('prop.dateErr2')); //输入的日期格式不正确(参考:2019-06-14 10:52:00)
                    return;
                }
            }

            //左右括号
            var leftBrackets = popWin.find('input[name="leftBrackets"]').val();
            var rightBrackets = popWin.find('input[name="rightBrackets"]').val();
            item['leftBrackets'] = leftBrackets;
            item['rightBrackets'] = rightBrackets;

            tmpStr = leftBrackets + tmpStr + rightBrackets;
            item['condition'] = tmpStr;
            var conType = popWin.find('select[name="conType"]');
            item['cType'] = conType.val();         //&& ||
            item['cTypeName'] = conType.find("option:selected").text();       //并且 或者

            return item;
        },

        _getAllCondition: function () {
            var items = this.tblObjArr.rows();
            var condition = '';
            $.each(items, function (i, item) {
                if (item) {
                    if (i == 0) {
                        condition = item.condition;
                    } else {
                        condition += item.cType + item.condition;
                    }
                }
            });
            return condition;
        },

        _applyPropertiesData: function (popWin, line) {
            var data = {};
            data['id'] = line.id;
            var routerName = popWin.find('input[name="routerName"]').val();

            function isNull(str) {
                if (str == "") return true;
                var regu = "^[ ]+$";
                var re = new RegExp(regu);
                return re.test(str);
            }

            if (isNull(routerName)) {
                return this._getLang('html.router.msg.routerNameNull');
            }
            if (routerName.length > 30) {
                return this._getLang('msg.tooLong.routerName');//'路由名称不能超过30个字符';
            }
            data['name'] = popWin.find('input[name="routerName"]').val();
            var sort = popWin.find('input[name="routerSort"]').val();
            if (sort) {
                sort = parseInt(sort);
                if (isNaN(sort)) {
                    sort = 1;
                }
                popWin.find('input[name="routerSort"]').val(sort);
            }

            data['sort'] = sort;
            data['memo'] = popWin.find('textarea[name="memo"]').val();

            if (line.fromNode.nodetype == 900) {
                var eNodes = '', iNodes = '';
                $.each(popWin.find('select[name="includes"] option') || [], function (i, option) {
                    if (option) {
                        iNodes += option.value + ';';
                    }
                });
                $.each(popWin.find('select[name="executions"] option') || [], function (i, option) {
                    if (option) {
                        eNodes += option.value + ';';
                    }
                });
                data['executions'] = eNodes;
                data['includes'] = iNodes;
            } else {
                var condition = this._getAllCondition();
                data['condition'] = condition == '' ? popWin.find('textarea[name="condition"]').val() : condition;
                data['conditionCn'] = this.tblObjArr.rows();
                data['bCondition'] = '';
                data['rule'] = this.__Flowdesigner.getRuleValue(popWin, 'router');
            }
            //相关数据的更新处理

            line.name = data.name;
            line._setName();

            //补全下一阶段信息
            data['nodeId'] = line.toNode.id;
            data['nodeName'] = line.toNode.name;
            data['nodeType'] = line.toNode.nodetype;

            line.data = data;
            line.fromNode.data['transitions'][line.id] = data;
            line.map['name'] = data.name;
            var title = this._getLang('prop.title')
                .replace('name', data.name)
                .replace('id', data.id);
            popWin.find('#hzPopModalLabel').html(title);
            return "";
        }

    };

    return LineProperties;
});

/**
 * 流程图定义
 * 入口
 * @author liys 201903
 */
define('flowdesigner/flowdesigner',['require','jquery','zrender','./element/FlowInit','./element/Swimlane','./element/node/StartNode','./element/node/TaskNode','./element/node/EndNode','./element/node/EventNode','./element/node/GatewayNode','./element/node/RobotNode','./element/node/ClusterNode','./element/node/VirtualNode','./element/node/SubflowNode','./element/FlowLine','./element/properties/FlowProperties','./element/properties/NodeProperties','./element/properties/LineProperties','./Template','bootstrap','confirm','jqueryui','mmGrid','ztree'],function (require) {
    var $ = require('jquery'),
        zRender = require('zrender'),
        FlowInit = require('./element/FlowInit'),
        SwimLane = require('./element/Swimlane'),
        StartNode = require('./element/node/StartNode'),
        TaskNode = require('./element/node/TaskNode'),
        EndNode = require('./element/node/EndNode'),
        EventNode = require('./element/node/EventNode'),
        GatewayNode = require('./element/node/GatewayNode'),
        RobotNode = require('./element/node/RobotNode'),
        ClusterNode = require('./element/node/ClusterNode'),
        VirtualNode = require('./element/node/VirtualNode'),
        SubflowGroup = require('./element/node/SubflowNode'),            //子流程对应的区域Group
        Route = require('./element/FlowLine'),
        FlowProperties = require('./element/properties/FlowProperties'),
        NodeProperties = require('./element/properties/NodeProperties'),
        LineProperties = require('./element/properties/LineProperties'),
        Template = require('./Template');

    //bootstrap加载
    require('bootstrap');
    //弹出框的插件加载
    require('confirm');
    //
    require('jqueryui');
    //表格插件加载
    require('mmGrid');
    //树插件加载
    require('ztree');

    var flowdesigner = {};

    var instance = null;

    flowdesigner.version = '20220228';
    //初始化系统方法
    flowdesigner.init = function (dom, opts) {
        //用来兼容IE浏览器
        if (typeof String.prototype.startsWith !== 'function') {
            String.prototype.startsWith = function (prefix, pos) {
                return this.substr(pos ? pos : 0, prefix.length) === prefix;
            };
        }

        //$.extend( [deep ], target, object1 [, objectN ] )
        //deep 可选。 Boolean类型 指示是否深度合并对象，默认为false。
        // 如果该值为true，且多个对象的某个同名属性也都是对象，则该"属性对象"的属性也将进行合并
        //target Object类型 目标对象，其他对象的成员属性将被附加到该对象上。
        //object1 可选。 Object类型 第一个被合并的对象。
        opts.version = this.version;
        var fd = new FlowDesigner(dom, opts, function (self) {
            var path = 'data/' + self.localeVal + '/';

            //配置文件分为三个来源
            //1.js默认内置，优先级最低（$.fn.horizonFlowDesigner.defaults）
            //2.配置文件config.json(优先级高于1)
            //3.初始化时传入的opts(优先级高于2)
            $.ajax({
                type: 'GET',
                dataType: 'json',
                url: path + 'config.json',
                data: '',
                async: false,
                cache: false,
                success: function (result) {
                    self.options = $.extend(true, {}, $.fn.horizonFlowDesigner.defaults, result, self.options);
                    //获取语言包数据
                    $.ajax({
                        type: 'GET',
                        dataType: 'json',
                        url: path + 'language.json',
                        data: '',
                        async: false,
                        cache: false,
                        success: function (result) {
                            self.options['language'] = result;
                            self._initDom();
                            self._initZrender();
                            self._bindEvent();
                        },
                        error: function () {
                            alert("language.json not found or format incorrect.");
                        }
                    });
                },
                error: function () {
                    alert("config.json not found or format incorrect.")
                    //opts = $.extend(true, {}, $.fn.horizonFlowDesigner.defaults, opts);
                }
            });
        });
        instance = (fd);
    };
    //对外提供一个可以不重新加载页面就可以切换指定数据的方法
    flowdesigner.reloadFlowById = function (dataid, ver) {
        if (instance == null) {
            console.log('系统未初始化,不能执行此方法.');
            return;
        }
        instance.reloadFlowById(dataid, ver);
    };
    flowdesigner.showMsg = function (msg, title, callback) {
        if (instance == null) {
            console.log('系统未初始化,不能执行此方法.');
            return;
        }
        instance.showMsg(msg, title, callback);
    };
    flowdesigner.loadConfig = function (key) {
        if (instance == null) {
            console.log('系统未初始化,不能执行此方法.');
            return null;
        }
        if (key == null) {
            return JSON.stringify(instance.options);
        }
        return instance.getOptions(key);
    };

    var base64DecodeChars = [
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
        -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
        15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
        -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
    ];

    var base64decode = function (str) {
        var c1, c2, c3, c4;
        var i, len, out;
        len = str.length;
        i = 0;
        out = '';
        while (i < len) {

            do {
                c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
            } while (i < len && c1 == -1);
            if (c1 == -1)
                break;

            do {
                c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
            } while (i < len && c2 == -1);
            if (c2 == -1)
                break;
            out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));

            do {
                c3 = str.charCodeAt(i++) & 0xff;
                if (c3 == 61)
                    return out;
                c3 = base64DecodeChars[c3];
            } while (i < len && c3 == -1);
            if (c3 == -1)
                break;
            out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));

            do {
                c4 = str.charCodeAt(i++) & 0xff;
                if (c4 == 61)
                    return out;
                c4 = base64DecodeChars[c4];
            } while (i < len && c4 == -1);
            if (c4 == -1)
                break;
            out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
        }
        return out;
    };
    var utf8to16 = function (str) {
        var out, i, len, c;
        var char2, char3;
        out = "";
        len = str.length;
        i = 0;
        while (i < len) {
            c = str.charCodeAt(i++);
            switch (c >> 4) {
                case 0:
                case 1:
                case 2:
                case 3:
                case 4:
                case 5:
                case 6:
                case 7:
                    out += str.charAt(i - 1);
                    break;
                case 12:
                case 13:
                    char2 = str.charCodeAt(i++);
                    out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
                    break;
                case 14:
                    char2 = str.charCodeAt(i++);
                    char3 = str.charCodeAt(i++);
                    out += String.fromCharCode(((c & 0x0F) << 12) |
                        ((char2 & 0x3F) << 6) |
                        ((char3 & 0x3F) << 0));
                    break;
            }
        }
        return out;
    };
    var _atob = window.atob || function (base64code) {
        return utf8to16(base64decode(base64code));
    };
    //图层对象,用于记录当前图层的相关数据
    var DrawLayer = function (fd, flowid) {
        var self = this;
        self.__Flowdesigner = fd;
        self.flowid = flowid;

        self.init();
    };

    DrawLayer.prototype = {
        constructor: DrawLayer,
        __Flowdesigner: null,
        minZ: 0,   //当前最低层数 ,间隔应该是10的倍数(0,10,20)

        flowid: null,
        parentFlowid: null,//上级流程
        parentNodeid: null,     //对应的子流程节点id
        //非开始结束节点数(当前流程已拖拽出的数量)
        nodeMax: 1,
        routeMax: 1,//路由数(当前流程已拖拽出的数量)

        data: null,      //当前画布的业务数据
        isMain: false,   //当前层是否为主流程(第一次打开的为主流程)
        //跟表单相关的数据
        forms: {},
        rules: {},//存放需要保存的规则页面内容

        _nodes: {},
        _routes: {},
        _swimlane: null,      //泳道
        zrGroup: null,
        rectShape: null,          //矩形包围的x,y最大最小值
        rectPoint: null,         //
        maxPoint: [0, 0],           //记录最大值,用于返回给外部使用
        maskRectShape: null,     //用来遮挡当前层的透明矩形
        rectMargin: 20,
        tPoint: null,  //点击鼠标时,记录临时鼠标位置
        tmpRoutes: {}, //用于流程跟踪图中的动态演示时查找对应的路由信息
        aloneNodes: {}, //用于流程监控时,存放不能在流程图显示的节点数据

        getZLevel: function (z) {
            return this.minZ + z;
        },
        //是否处于缩放状态
        isScale: function () {
            return this.zrGroup.scale[0] != 1;
        },
        getScale: function () {
            return "[" + this.zrGroup.scale + "]";
        },
        //是否移动位置了
        isPosition: function () {
            if (this.zrGroup.position[0] == 0 && this.zrGroup.position[1] == 0) {
                return false;
            }
            return true;
        },
        getPosition: function () {
            return "[" + this.zrGroup.position + "]";
        },
        //初始化层数据
        init: function () {
            this.nodeMax = 1;
            this.routeMax = 1;

            this.data = {};
            this.data.flowInfo = {flowName: ''};
            this.data.process = {};
            this.data.mapData = {};
            this.data.mapData.nodes = {};
            this.data.mapData.lines = {};

            this._nodes = {};
            this._routes = {};
            this._swimlane = null;

            this.rectPoint = {
                minX: 1000,
                minY: 1000,
                maxX: 0,
                maxY: 0
            };
            this.tPoint = null;
            this.zrGroup = new zRender.Group({
                tx: 0,
                ty: 0
            });
            this.makeRoundRect();
            this.makeMaskRect();
        },
        //创建包围对象
        makeRoundRect: function () {
            this.rectShape = new zRender.Rect({
                z: 0,
                style: {
                    opacity: 0.85,
                    lineWidth: 1,
                    fill: '#f0f0f0',
                    stroke: '#bebebe',
                    strokeNoScale: true, //描边粗细不随缩放而改变，false 则会根据缩放同比例缩放描边粗细。
                    transformText: true //文字是否跟随变换效果，仅对 Path 或 Image 元素有效
                },
                shape: {
                    x: 0,
                    y: 0,
                    width: 10,
                    height: 10
                }
            });
            this.rectShape.hide();
            this.zrGroup.add(this.rectShape);
        },
        //遮挡层
        makeMaskRect: function () {
            var opacity = this.__Flowdesigner.options['subOpacity'][0];
            this.maskRectShape = new zRender.Rect({
                z: this.getZLevel(this.__Flowdesigner.zArr.selected + 1),
                style: {
                    opacity: opacity,
                    lineWidth: 1,
                    fill: '#f0f0f0',
                    stroke: '#f0f0f0',
                    strokeNoScale: true, //描边粗细不随缩放而改变，false 则会根据缩放同比例缩放描边粗细。
                    transformText: true //文字是否跟随变换效果，仅对 Path 或 Image 元素有效
                },
                shape: {
                    x: 0,
                    y: 0,
                    width: this.__Flowdesigner.zrender.getWidth(),
                    height: this.__Flowdesigner.zrender.getHeight()
                }
            });
            this.maskRectShape.hide();
            this.zrGroup.add(this.maskRectShape);
        },
        //清除层数据对象
        clearCanvas: function () {
            this.zrGroup.dirty();
            //删除画布上的图形
            this.zrGroup.removeAll();
            this.zrGroup.attr({
                position: [0, 0],
                scale: [1, 1],
                origin: [0, 0]
            });
            //节点路由数据清空
            this.data.process = {};
            this.data.mapData.nodes = {};
            this.data.mapData.lines = {};

            this.nodeMax = 1;
            this.routeMax = 1;
            this._nodes = {};
            this._routes = {};
            this._swimlane = null;
            this.tPoint = null;

            this.backimg = null;
            this.parentFlowid = null;
            this.parentNodeid = null;
        },
        //当页面上的节点或者路由或者泳道变化拖动时
        chgForShapeDrag: function (x, y) {
            this.checkNodePoint(x, y);
            this.refreshRect();
        },
        //路由点的边界判断
        checkPoint: function (x, y) {
            var point = this.rectPoint;
            if (x > 0) {
                point.minX = Math.min(point.minX, x);
                point.maxX = Math.max(point.maxX, x);
            }
            if (y > 0) {
                point.minY = Math.min(point.minY, y);
                point.maxY = Math.max(point.maxY, y);
            }
        },
        //路由折线点边界判断
        checkLinePoint: function (x, y) {
            this.checkPoint(x - this.rectMargin + 1, y - this.rectMargin + 1);
            this.checkPoint(x + this.rectMargin, y + this.rectMargin);
        },
        //节点的边界判断
        checkNodePoint: function (x, y) {
            this.checkPoint(x - 5, y - 5);
            this.checkPoint(x + 60, y + 75);
        },
        //泳道的边界判断
        checkSwimPoint: function () {
            var width = this._swimlane.cutWidth;
            if (this._swimlane.lanetype == 1) {
                this.checkPoint(width, 0);
            } else {
                this.checkPoint(0, width + 30);//横向泳道时,高度需要加上标题的高度
            }
            this.checkPoint(1, 1);
        },
        //对所有点对边界判断
        checkAllPoint: function () {
            var self = this;
            this.rectPoint = {
                minX: 1000,
                minY: 1000,
                maxX: 0,
                maxY: 0
            };
            $.each(this._nodes || [], function (i, node) {
                if (node) {
                    self.checkNodePoint(node.x, node.y);
                }
            })

            $.each(this._routes || [], function (i, route) {
                if (route && route.dragPoints.length == 3) {
                    self.checkLinePoint(route.dragPoints[2].x, route.dragPoints[2].y);
                }
            })
            if (self._swimlane) {
                self.checkSwimPoint();
            }
            self.maxPoint = [self.rectPoint['maxX'], self.rectPoint['maxY']];
        },
        //刷新包围对象
        refreshRect: function (checkAll) {
            if (!(checkAll || this.rectShape.ignore)) {
                this.checkAllPoint();
            }
            var point = this.rectPoint;
            //把子流程移动到子流程节点位置
            this.rectShape.attr({
                z: this.minZ,
                shape: {
                    x: point.minX - 10,
                    y: point.minY - 15,
                    width: point.maxX - point.minX + 30,
                    height: point.maxY - point.minY + 15
                }
            });
        },
        //缩放
        scaleGroup: function (zoom, origin) {
            var sc = this.zrGroup.scale[0];
            sc = parseFloat((sc += 0.1 * zoom).toFixed(1));

            if (zoom == 0) {
                sc = 1;
            } else if (sc < 0.1) {
                sc = 0.1;
            }
            if (!origin) {
                origin = [0, 0];
            }
            this.zrGroup.attr({
                scale: [sc, sc],
                origin: [0, 0]//origin //当前鼠标位置为中心
            });
        },
        //开始拖动时,标记位置信息
        startDrag: function (param) {
            this.tPoint = {
                x: param.event.zrX,
                y: param.event.zrY,
                px: this.zrGroup.position[0],
                py: this.zrGroup.position[1]
            };
        },
        //拖动
        dragGroup: function (param) {
            var point = this.tPoint;//开始位置信息
            var movePosition = [
                param.event.zrX - point.x + point.px,
                param.event.zrY - point.y + point.py
            ];
            this.zrGroup.attr({
                position: movePosition
            });
        },
        //恢复缩放
        restoreScale: function () {
            this.zrGroup.attr({
                scale: [1, 1]
            });
        },
        //恢复拖动
        restoreDrag: function () {
            this.zrGroup.attr({
                position: [0, 0]
            });
        },
        //恢复缩放和拖动
        restoreAll: function () {
            this.checkAllPoint();
            this.zrGroup.attr({
                scale: [1, 1],
                position: [0, 0]
            });
        },
        //获取包围矩形的中心点
        getCenterPoint: function () {
            var point = this.rectPoint;
            return [(point.maxX + point.minX) / 2, (point.maxY + point.minY) / 2];
        },
        //获取在有无泳道的情况下,节点的顶点能到达的极限位置
        getMinPoint: function (point, posY) {
            var minX = 20, minY = 20;    //默认为20
            var swimlane = this._swimlane;
            if (swimlane) {
                if (swimlane.lanetype == 1) {
                    //纵向
                    minY = 60;
                    minX = 25;
                } else {
                    minX = 30;
                    minY = 30 + (posY ? posY : 0);
                }
            }
            var x = Math.max(point[0], minX);
            var y = Math.max(point[1], minY);
            return [x, y];
        },
    };

    var FlowDesigner = function (dom, opts, callback) {
        var self = this;
        opts = opts || {};
        //id和showtype时必须要传入的参数,id可以是flowid也可以是workid
        if (opts.id) {
            self.dataid = self.id = opts.id;
        }
        if (opts.showtype) {
            self.showtype = opts.showtype;
        }
        //传入当前打开的人员信息,用于记录
        if (opts.userid) {
            self.userid = opts.userid;
        }
        if (opts.username) {
            self.username = opts.username;
        }
        if (!(!opts.tenantid || opts.tenantid == '' || opts.tenantid == 'null')) {
            self.tenantid = opts.tenantid;
        }
        if (!(!opts.identifier || opts.identifier == '' || opts.identifier == 'null')) {
            self.identifier = opts.identifier;
        }
        if (opts.version) {
            self.version = 'Build:' + opts.version + '.1';
        }
        //showtype=2时,显示流程跟踪图时,用来确定当前打开的节点
        if (!(!opts.nodeid || opts.nodeid == '' || opts.nodeid == 'null')) {
            self.nodeid = opts.nodeid;
        }

        //传入一个已经存在的数据,用来显示,此参数传入仅为来将来可以扩展图形显示
        if (opts.data) {
            self.data = opts.data;
        }

        self.options = opts;
        self.container = dom;

        self.nodemove = opts['nodemove'] ? opts['nodemove'] : 0;

        self._loadData(null, callback);
    };

    FlowDesigner.prototype = {
        constructor: FlowDesigner,
        CONTINUE: true,
        BREAK: false,

        version: 'Build:20200526',//记录修改版本日期
        curDrawLayer: null,  //当前层对象DrawLayer
        drawLayers: {},//所有展现过的图层数据
//标记当前显示的方式,1=设计/2=流程跟踪图/3=监控图/4=自动测试/5=实例修改/6自由提交时选择位置/7=流程图展示
        showtype: 1,
        dataid: null,    //获取数据时的id,可能为flowid也可能是workid
        userid: 'admin', //打开流程图的人员信息
        username: 'Admin',//默认管理员
        mwheelEnable: false,//流程跟踪图上是否使用滚轮
        // tenantid:'system',//租户id
        // identifier:'system',//数据源id
        flowid: null,    //流程id,不论传入的dataid是flowid还是workid,都可以从map中获取到对应的flowid
        nodeid: null,    //流程跟踪图显示时,用来传入的当前节点

        nodemove: 0,     //节点移动缓冲范围
        data: null,      //数据信息
        maxVer: 0,       //记录当前流程的最大版本号,为打开历史版本

        //当前选中的线的类型1--直线,2--折线
        ckLineType: null,
        ckLineObj: null,    //当前选中的线的类型对象,用于互斥显示
        ckSelect: true,     //是否运行选择多个节点用于对齐处理
        ckPartObj: null,     //选择对象本身,用于取消选择

        //当前选中的节点对象
        selNodeHandler: null,
        //当前选中的路由对象
        selLineHandler: null,
        selSwimlaneHandler: null,
        //当前拖动的路由对象
        dragLineHandler: null,

        //区域选中的节点列表
        selAreaNodes: [],
        startSelArea: false,//开始拖动选择
        dragRectShape: null, //拖动矩形框对象
        startDragRectShape: false,//标记是否可以开始拖动选择区域
        tmpImgShapeForSub: null,//显示子流程时,用于显示主流程临时图片的对象
        positionLine: [],        //垂直线,用于showtype=6时选择坐标点
        zArr: {
            swimlane: 1,     //1,6切换
            route: 2,        //2,3切换
            node: 4,         //4,5切换
            selected: 6      //6,1切换
        },

        appName: ['%E6%8', '5%20%E4%BD%9', '5%A7%20%E6%A', 'C%20%E', 'D%A3%20%E5%B7%A', '6%B5%81'],

        statusPos: null,
        statusFlowname: null,
        statusFlowid: null,
        statusType: null,

        tooltipTxt: null,    //浮动显示层信息
        menuContainer: null, //菜单显示层对象
        //初始化层数据对象
        //初始化画图层

        _initDrawLayer: function () {
            this.curDrawLayer = new DrawLayer(this, this.flowid);
            this.drawLayers = {};
            this.drawLayers[this.flowid] = this.curDrawLayer;
            this.zrender.add(this.curDrawLayer.zrGroup);
        },
        //初始化整体框架
        _initDom: function () {
            var self = this;
            var $container = $(self.getHtml('template/container.html'));
            var $parts = $container.find('.fd-parts');
            if (self.showtype == 1 || self.showtype == 5 || self.showtype == 8) {
                //拖拽节点/路由元素
                $parts.append(self.getHtml(self.showtype == 8 ? 'template/part8.html' : 'template/part.html'));

                //增加打开本地文件的文件控件
                var $file = $('<input type="file" id="files" style="display: none">');
                $file.on('change', function () {
                    self._fileImport(this);
                });
                $container.append($file);
                //弹出窗口
                var $popwin = $(self.getHtml('template/popwin.html'));
                //屏蔽右键
                $popwin.contextmenu(function (e) {
                    e.preventDefault();//屏蔽cavans的菜单
                });

                // $container.append($popwin);
                $(this.container).parent().append($popwin);
                //模态窗口显示时,
                //属性框居中
                $(window).on('resize', function () {
                    self._centerModals();
                });
            } else {
                $container = $('<div class="fd-container"><div class="fd-main"><div class="fd-canvas"></div></div></div>');
                var $fdmain = $container.find('.fd-main'); //top =56 -> 0
                $fdmain.css("top", 5);
                var $fdcanvas = $container.find('.fd-canvas'); //left = 25 -> 5
                $fdcanvas.css("left", 5);
            }

            $(this.container).append($container);
            $container.on('click', function () {
                //20200402 LIYS 把if条件判断去掉，因为再缩放状态下显示菜单后，点击空白处无法隐藏菜单
                //20200407 LIYS if条件去掉后，菜单不能正常出来了
                if (!(self.showtype == 1 || self.showtype == 5)) {
                    self._hideContextMenu();//点击在其他地方时,把弹出菜单隐藏
                }
            });
            $(this.container).contextmenu(function (e) {
                e.preventDefault();//屏蔽cavans的菜单
            });

        },
        //框架上的图标绑定事件处理
        _bindEvent: function () {
            var self = this;
            if (this.showtype == 1 || this.showtype == 5 || this.showtype == 8) {
                var opts = self.options,
                    $container = $(self.container);

                $container
                    .on('selectstart', function () {
                        return false;
                    })
                    .on('mousemove', function (ev) {
                        $(this).trigger('fd.mousemove', [ev]);
                    })
                    .on('mouseup', function (ev) {
                        $(this).trigger('fd.mouseup', [ev]);
                    });

                $container.find('.fd-part')
                    .on('mousedown', function () {
                        // console.log('fd-part...mousedown....2');
                        self._hideContextMenu();
                        if (self.curDrawLayer.isScale()) {
                            return;
                        }
                        var $this = $(this),
                            part = $this.attr('data-part');

                        if (part == 'Start') {
                            if (self.curDrawLayer._nodes['Start']) {
                                return;
                            }
                        }
                        var $partDrag = $container.find('.fd-part-drag'),
                            $canvasMask = $container.find('.fd-canvas-mask');
                        // IE11下 css('background')好像不行呀,该怎么改呢
                        // var pImg = $this.children('.fd-part-img');
                        //css('background'),在IE下获取为空,造成出不来小图片,使用background-image
                        $partDrag.css({
                            background: $this.children('.fd-part-img').css('background-image')
                        });
                        $container
                            .on('fd.mousemove', function (e, ev) {
                                var image = opts.part.image;
                                $partDrag.css({
                                    left: (ev.clientX - image.width / 2) + 'px',
                                    top: (ev.clientY - image.height / 2) + 'px'
                                }).show();
                                $canvasMask.show();
                            })
                            .on('fd.mouseup', function (e, ev) {
                                if ($(ev.target).is($canvasMask)) {
                                    // ev = zRender.normalizeEvent(ev.target, ev);
                                    var type = opts.part.defaultType[part];
                                    var image = opts.flownode.image;
                                    var x = ev.offsetX;//ev.clientX;
                                    var y = ev.offsetY;
                                    var element = self._makeFlowNode({
                                        id: part,
                                        nodetype: type,
                                        name: self.getLang('parts')[part],
                                        x: Math.max(0, x - image.width / 2),
                                        y: Math.max(0, y - image.height / 2)
                                    });
                                    element.addSelfToZr();
                                    self.curDrawLayer.checkNodePoint(element.x, element.y);
                                }

                                $partDrag.hide();
                                $canvasMask.hide();
                                self.hideProperties();
                                $container.off('fd.mousemove').off('fd.mouseup');
                            });
                    });

                $container.find('.fd-part-ck')
                    .on('click', function () {
                        // console.log('fd-part-ck...click....4');
                        var $this = $(this),
                            part = $this.attr('data-part');
                        switch (part) {
                            case 'line':
                            case 'brokenline':
                                if (self.ckLineObj) {
                                    var tmpPart = self.ckLineObj.attr('data-part');
                                    if (tmpPart != part) {
                                        self.ckLineObj.removeClass('selected');
                                        self.ckLineObj = null;
                                    }
                                }
                                if ($this.hasClass('selected')) {
                                    $this.removeClass('selected');
                                    self.ckLineType = null;
                                    self.ckLineObj = null;
                                } else {
                                    $this.addClass('selected');
                                    self.ckLineType = part == 'line' ? 1 : 2;    //默认直线
                                    self.ckLineObj = $this;
                                }
                                break;
                            case 'swimlanes':
                                self._swimlanes();
                                break;
                            case 'select':
                                self._ckSelectPart();
                                break;
                            case 'align':
                                self._alignNode();
                                break;
                            case 'gridlines':
                                var $canvas = $container.find('.fd-canvas');
                                if ($this.hasClass('selected')) {
                                    $canvas.removeClass('selected');
                                    $this.removeClass('selected');
                                } else {
                                    $canvas.addClass('selected');
                                    $this.addClass('selected');
                                }
                                break;
                            case 'file':
                                self._ckFile();
                                break;
                            case 'zoomout':
                                self._doZoom(self.curDrawLayer.zrGroup, 1);
                                break;
                            case 'zoomin':
                                self._doZoom(self.curDrawLayer.zrGroup, -1);
                                break;
                            case 'zoomreset':
                                self._doZoom(self.curDrawLayer.zrGroup, 0);
                                break;
                            case 'clear':
                                self._ckClearCanvas();
                                break;
                        }
                        if (part != 'file') {
                            self._hideContextMenu();
                        }
                    });
                //选择默认是选中的状态,所以需要在初始化的时候赋值
                this.ckPartObj = $container.find('[data-part="select"]');
            }
            $(window).on('resize.fd-canvas', function () {
                self.zrender.resize();
                $.each(self.drawLayers || [], function (i, drawLayer) {
                    if (drawLayer && drawLayer._swimlane) {
                        drawLayer._swimlane.zrResize();
                    }
                });

            });

        },
        //创建一个新节点对象
        _makeFlowNode: function (opt) {
            var element = null;
            opt['__Flowdesigner'] = this;
            if (!opt['__drawLayer']) {
                opt['__drawLayer'] = this.curDrawLayer;
            }
            var point = opt['__drawLayer'].zrGroup.position;
            opt.x -= point[0];
            opt.y -= point[1];

            if (opt.x < 20) {
                opt.x = 20;
            }
            if (opt.y < 20) {
                opt.y = 20;
            }
            var nodetype = parseInt(opt.nodetype);
            //在从数据恢复时,nodetype需要处理
            if (nodetype < 10) {
                // public static final int Node_Start 	= 0; 	//人工开始
                // public static final int Node_Timer_Start = 1;//定时开始
                // public static final int Node_Signal_Start = 2;//信号开始
                // public static final int Node_Msg_Start = 3;//消息开始
                nodetype = 0;
            } else if (nodetype < 40 || nodetype == 50) {
                // public static final int Node_Single = 10; //单人处理节点(单一,多人单一)
                // public static final int Node_Multi_Single = 11;//多人单一节点
                // public static final int Node_Multi = 20; //多人并行处理节点
                // public static final int Node_Order = 25; //多人顺序处理节点
                // public static final int Node_Merger = 30;
                // public static final int Node_Progressively = 50;//逐级审批节点
                nodetype = 10;
            } else if (nodetype < 50) {
                // public static final int Node_Auto = 40;			//自动节点
                // public static final int Node_Auto_Program = 41;//自动程序
                // public static final int Node_Auto_Rule = 42;//自动业务规则
                // public static final int Node_Auto_Service = 43;//自动服务任务
                nodetype = 41;
            } else if (nodetype < 70) {

            } else if (nodetype < 80) {

                // public static final int Node_Gateway = 70;	//网关
                // public static final int Node_GateWay_Split = 71;//分支网关
                // public static final int Node_GateWay_Merge = 72;//合并网关
                nodetype = 72;
            } else if (nodetype < 90) {
                // public static final int Node_Event= 80;
                // public static final int Node_Event_Intermediate = 81;//中间事件
                // public static final int Node_Event_Timer = 82;//定时事件
                // public static final int Node_Event_Message = 83;//消息事件
                // public static final int Node_Event_Signal_Throw = 84;//信号抛出事件
                // public static final int Node_Event_Signal_Catch = 85;//信号捕获事件
                nodetype = 81;
            } else if (nodetype == 101) {
                // public static final int Node_End 	= 100;
                // public static final int Node_End_Instance = 101;//实例结束
                nodetype = 100;
            }
            // public static final int  Node_Mutual 	= 210;	//多引擎交互节点
            // public static final int Node_Virtual 	= 900;//虚拟节点(全部)

            switch (nodetype) {
                case 0:
                    element = new StartNode(opt);
                    break;
                case 10:
                    element = new TaskNode(opt);
                    break;
                case 81:
                    element = new EventNode(opt);
                    break;
                case 72:
                    element = new GatewayNode(opt);
                    break;
                case 41:
                    element = new RobotNode(opt);
                    break;
                case 210:
                    element = new ClusterNode(opt);
                    break;
                case 60:
                    element = new SubflowGroup(opt);
                    break;
                case 900:
                    element = new VirtualNode(opt);
                    break;
                case 100:
                    element = new EndNode(opt);
                    break;
            }
            return element;
        },
        //初始化画布对象,设计状态
        _initZrender: function () {
            var self = this, zr = null;
            var $container = $(this.container);
            var $canvas = $container.find('.fd-canvas'),
                zr = this.zrender = zRender.init($canvas[0]);

            self.menuContainer = $('<div class="context-menu"></div>');
            self.tooltipTxt = $('<div class="flowchart-title"></div>');
            $canvas.append(self.menuContainer);
            $canvas.append(self.tooltipTxt);

            self.menuContainer.hide();
            self.tooltipTxt.hide();

            switch (self.showtype) {
                case 1:     //1.流程定义编辑
                case 5:     //5.实例定义编辑
                    self._initZrender_Designer($canvas, zr);
                    break;
                case 2:     //2.流程跟踪图
                case 3:     //3流程监控,
                case 4:     //4自动测试,
                case 7:     //7.流程图展示
                    self._initZrender_Monitor(zr);
                    break;
                case 6:     //6位置选择,自由提交时前端操作使用
                    self._initZrender_Position(zr);
                    break;
                case 8:     //8.全局图定义
                    self._initZrender_GeneralDesigner($canvas, zr);
                    break;
                case 9:     //9.全局图展示
                    self._initZrender_GeneralShow(zr);
                    break;
            }

            zr.on('contextmenu', function (param) {
                self._showFlowMenu(param);
            });
            zr.on("mousewheel", function (param) {
                self._mousewheel(param);

                if (self.showtype == 2) {
                    //在允许图形缩放时，阻止滚轮事件往上传递，造成主页面滚动
                    if (self.mwheelEnable) {
                        param.event.preventDefault();
                        param.event.returnValue = false;
                    }
                }
            });
        },
        //编辑流程图时初始化工具栏和事件绑定
        _initZrender_Designer: function ($canvas, zr) {
            var self = this;
            var status = $(self.getHtml('template/status.html'));
            $canvas.append(status);
            $canvas.append('<div class="fd-canvas-mask"></div>');

            var user = status.find('.fd-bar[data-part="user"]').find('.fd-bar-text')[0];
            $(user).html(self.username);
            self.statusPos = $(status.find('.fd-bar[data-part="pos"]').find('.fd-bar-text')[0]);
            self.statusFlowname = $(status.find('.fd-bar[data-part="flowname"]').find('.fd-bar-text')[0]);
            self.statusFlowid = $(status.find('.fd-bar[data-part="flowid"]').find('.fd-bar-text')[0]);
            self.statusType = $(status.find('.fd-bar[data-part="type"]').find('.fd-bar-text')[0]);

            $(status.find('.fd-bar[data-part="ver"]').find('.fd-bar-title')[0]).html(self.version);
            self.statusPos.html('0,0');
            zr.on('mousedown', function (param) {
                // console.log("1.FD___mousedown.  x="+param.event.zrX+",y="+param.event.zrY
                //     +"---"+ param.event.button);
                if (param.event.button == 2) {
                    // console.log('右键点击');
                    return;
                }
                if (self.curDrawLayer.isScale()) {
                    //20200407 LIYS 缩放状态下显示菜单后，点击空白处无法隐藏菜单
                    self._hideContextMenu();//点击在其他地方时,把弹出菜单隐藏
                    //如果在缩放状态下,不论点击在哪,都执行拖动
                    self._startDragGroup(param);
                    return;
                }
                //20200331 LIYS 根据点击位置和是否选择区域来处理是否取消
                if (self.dragRectShape && !self.dragRectShape['del']) {
                    //判断点击点是否在矩形内
                    if (param.target == self.dragRectShape) {
                        self.startDragRectShape = true;
                        //还需要记录当前点位置
                        self.dragRectShape.startPoint = [param.event.zrX, param.event.zrY];
                        return;
                    }
                }
                //鼠标只要在画布上按下时,就取消已经选中的区域
                self._cancelArea();
                self.hideTitle();

                if (!self._isClickInShape(param)) {
                    //在空白处点击时执行,如果在节点和路由上点击,则在对应的对象click事件中根据情况执行
                    //取消节点和路由的选中状态
                    self.cancelSel();
                    //对路由拖动的处理
                    self._mousedown_dragLine();

                    self._mousedown_startsel(param);
                }
            });
            zr.on('mousemove', function (param) {
                // console.log("2.FD___mouseover...."+self.startSelArea +","+param.event.button);
                var msg = parseInt(param.event.zrX) + "," + parseInt(param.event.zrY);
                self.statusPos.html(msg);

                //画线时的移动需要处理
                if (self.dragLineHandler) {
                    //当前画布被拖动时,需要增加位移
                    var mPoint = self.curDrawLayer.zrGroup.position;
                    if (self.dragLineHandler.fromNode) {
                        self.dragLineHandler.x2 = param.event.zrX - 4 - mPoint[0];
                        self.dragLineHandler.y2 = param.event.zrY - 4 - mPoint[1];
                    } else if (self.dragLineHandler.toNode) {
                        self.dragLineHandler.x1 = param.event.zrX - 4 - mPoint[0];
                        self.dragLineHandler.y1 = param.event.zrY - 4 - mPoint[1];
                    }
                    self.dragLineHandler.refresh();
                } else if (self.startSelArea) {//此状态,拖动和选择共用
                    if (self.curDrawLayer.isScale()) {
                        //如果时缩放状态,则执行拖动
                        self.curDrawLayer.dragGroup(param);
                    } else if (self.ckSelect) {//处于允许选择状态时,执行选择
                        var w = param.event.zrX - self.dragRectShape.shape.x;
                        var h = param.event.zrY - self.dragRectShape.shape.y;
                        if (w == 0 || h == 0) {
                            return;
                        }
                        self.dragRectShape.attr({
                            del: false,
                            shape: {
                                width: w,
                                height: h
                            }
                        });
                        self._checkInRect();
                    } else {
                        //否则执行拖动处理
                        self.curDrawLayer.dragGroup(param);
                    }
                }
                //20200331 LIYS 整体移动选择区域
                else if (self.startDragRectShape) {
                    self._dragSelArea(param.event.zrX, param.event.zrY);
                }
            });
            zr.on('mouseup', function (param) {
                //20200331 LIYS 判断选择区域内是否有对象存在，如果没有选中任何节点，则隐藏
                if (self.selAreaNodes.length == 0) {
                    self._hiddenArea();
                } else {
                    self.dragRectShape.attr({
                        cursor: 'move'
                    });
                }
                self.startSelArea = false;
                self.startDragRectShape = false;
            });
        },
        //全局定义
        _initZrender_GeneralDesigner: function ($canvas, zr) {
            var self = this;
            zr.on('mousedown', function (param) {

            });
            zr.on('mousemove', function (param) {

            });
            zr.on('mouseup', function (param) {

            });
        },
        _initZrender_GeneralShow: function (zr) {

        },
        //监控显示需要用到的事件绑定
        _initZrender_Monitor: function (zr) {
            var self = this;
            zr.on('mousedown', function (param) {
                if (param.event.button == 0) {
                    self._startDragGroup(param);
                }
            });
            zr.on('mousemove', function (param) {
                if (self.startSelArea) {
                    self.curDrawLayer.dragGroup(param);
                }
            });
            zr.on('mouseup', function (param) {
                self.startSelArea = false;
            });

        },
        _initZrender_Position: function (zr) {
            var self = this;
            zr.on('mousedown', function (param) {
                //返回坐标值
                if (param.event.button == 2) {
                    self._startDragGroup(param);
                } else {
                    if (!self._isClickInShape(param)) {
                        var mPoint = self.curDrawLayer.zrGroup.position;
                        var x = parseInt(param.event.zrX - mPoint[0]); //parseInt是为了IE11下不出现小数点
                        var y = parseInt(param.event.zrY - mPoint[1]);
                        //转换为中心点位置
                        gPositionBack(x - 25, y - 25);
                    } else {
                        self.showMsg(self.getLang('static.selposerr'))
                    }
                }
            });
            zr.on('mousemove', function (param) {
                if (self.startSelArea) {
                    self.curDrawLayer.dragGroup(param);
                }
                var x = param.event.zrX;
                var y = param.event.zrY;
                self._movePosLine([x, y]);
            });
            zr.on('mouseup', function (param) {
                self.startSelArea = false;
            });

        },
        //流程跟踪图中用到的特殊对象
        _initIconForTracklog: function () {
            var position = this.options.iconPosition;
            var colors = this.options.flownode.color;
            var text = this.options.flownode.colorTip;
            var self = this;
            var x = 0, y = 0;
            //获取一下图像上最大点的坐标
            this.curDrawLayer.checkAllPoint();
            var point = this.curDrawLayer.rectPoint;

            if (isNaN(position.x)) {
                if (position.x == 'left') {
                    x = 0;
                } else {//if(position.x == 'right'){
                    x = point.maxX;//this.zrender.getWidth() ;
                }
            } else {
                x = position.x;
            }

            x += position.xpos;
            if (isNaN(position.y)) {
                if (position.y == 'top') {
                    y = 17;
                } else {
                    y = point.maxY + 20; //this.zrender.getHeight()-7 ;
                }
            } else {
                y = position.y;
            }
            y += position.ypos;
            var pos = 0;
            var mx = x, my = y;
            if (position.isH) {
                //横排
                if (position.x == 'right') {
                    x -= 400;//5*80
                }
                if (x < 1) {
                    x = 1;
                }
                if (y < position.ymin) {
                    y = position.ymin;
                }
                var length = 0;
                $.each(colors || [], function (key, color) {
                    if (color) {
                        self._makeIconCircle(self.curDrawLayer.zrGroup, color, length, y,
                            text[key], position['opacity']);
                        length = length + (text[key].length * 4) + 60;
                    }
                })
                mx = x + (pos) * 80 + 5 + 20;
                my = y + 10;
                self._makeIconRect(this.curDrawLayer.zrGroup, x, y - 15, length + 10, 20, position['opacity']);
            } else {
                //竖排
                if (position.x == 'right') {
                    x -= 105;//5*80
                }
                if (position.y == 'bottom') {
                    y -= 85
                }

                $.each(colors || [], function (key, color) {
                    if (color) {
                        self._makeIconCircle(self.curDrawLayer.zrGroup, color, x, y + (pos++) * 20,
                            text[key], position['opacity']);
                    }
                })
                mx = x + 100 + 10;
                my = y + pos * 20 + 5 + 10;
                self._makeIconRect(this.curDrawLayer.zrGroup, x, y - 17, 100, pos * 20 + 5, position['opacity']);
            }

            //当前页面对象的最大坐标值
            this.curDrawLayer.maxPoint = [Math.max(point['maxX'], mx), Math.max(point['maxY'], my)];
        },
        //流程跟踪图,图例矩形
        _makeIconRect: function (shape, x, y, w, h, opacity) {
            var rect = new zRender.Rect({
                z: 9,
                style: {
                    opacity: opacity ? opacity : 1,
                    lineWidth: 2,
                    fill: '#fff',
                    stroke: '#bebebe'
                },
                shape: {
                    x: x,
                    y: y,
                    width: w,
                    height: h
                }
            });
            shape.add(rect);
        },
        //流程跟踪图,图例颜色对象
        _makeIconCircle: function (shape, color, x, y, text, opacity) {
            var img = new zRender.Circle({
                z: 10,
                style: {
                    stroke: color,
                    fill: color,
                    opacity: opacity ? opacity : 1
                },
                position: [10, -5],
                shape: {
                    cx: x,
                    cy: y,
                    r: 6
                }
            });
            var txt = new zRender.Text({
                z: 10,
                style: {
                    x: x + 20,
                    y: y - 3,
                    opacity: opacity ? opacity : 1,
                    textPosition: 'inside',
                    textAlign: 'left',
                    textVerticalAlign: 'middle',
                    text: text
                }
            });

            shape.add(img);
            shape.add(txt);
        },
        //创建两条垂直相交线
        _makeTwoLine: function () {
            var self = this;
            this.positionLine = [];
            $.each([0, 1], function (i, value) {
                self.positionLine.push(new zRender.Line({
                    // z:999,
                    style: {
                        strokeNoScale: true, //描边粗细不随缩放而改变，false 则会根据缩放同比例缩放描边粗细。
                        stroke: '#429709',
                        lineWidth: 2,
                        lineDash: [4, 1]
                    },
                    shape: {
                        x1: 0,
                        y1: 0,
                        x2: i == 0 ? self.zrender.getWidth() : 0,
                        y2: i == 1 ? self.zrender.getHeight() : 0
                    }
                }));
            });
            self.zrender.add(this.positionLine[0]);
            self.zrender.add(this.positionLine[1]);
        },
        _movePosLine: function (point) {
            this.positionLine[0].attr({
                shape: {
                    y1: point[1],
                    y2: point[1]
                }
            });
            this.positionLine[1].attr({
                shape: {
                    x1: point[0],
                    x2: point[0]
                }
            })
        },
        //水印
        _initWatermark: function (canvas, watermark) {
            var self = this;
            var _watermark = typeof watermark === 'string' ? watermark : '';
            if (!(_watermark && _watermark.replace(/ /g, '').length)) {
                if (typeof this.appName === 'object') {
                    $.each([0, 0, 0, 0, 0, 0], function (i) {
                        _watermark += self.appName[i > 2 ? (i * 2) - 5 : i * 2];
                    });
                    _watermark = decodeURIComponent(_watermark);
                } else {
                    return false;
                }
            } else {
                _watermark = this._decodeData(_watermark);
            }
            //TODO 如果是流程跟踪图,则根据图像大小调整,未完成
            if (this.showtype == 2) {
                var $container = $(this.container);
                // $container.css("height",200);

                // var $fdmain = $container.find('.fd-main');

            }

            var w = parseInt(this.zrender.getWidth() * 3 / 4),
                h = parseInt(this.zrender.getHeight() * 3 / 4),
                fontSize = 100;

            fontSize = w / _watermark.length;
            var waterOpacity = (self.options['waterOpacity'] || 0.02);
            waterOpacity = waterOpacity < 0.02 ? 0.02 : waterOpacity;

            var wt = (new zRender.Text({
                z: -1,
                position: [0, 0],
                rotation: [Math.PI / 12],
                origin: [w / 2, h / 2],
                cursor: 'default',
                style: {
                    opacity: waterOpacity,
                    x: w / 2,
                    y: h / 2 + (fontSize / 2 - 10),
                    fill: '#f2f2f2',
                    font: fontSize + 'px Microsoft Yahei',
                    textPosition: 'inside',
                    textAlign: 'center',
                    textVerticalAlign: 'center',
                    text: _watermark
                }
            }));
            canvas.add(wt);
            return wt;
        },
        //解码处理
        _decodeData: function (data) {
            $.each([0, 0], function (i) {
                data = _atob(data.replace(/[\n\r]/g, ''));
            });
            data = decodeURIComponent(data);//encodeURIComponent
            return data;
        },

        //判断鼠标是否点击在画布上的对象上(节点,路由,泳道)
        _isClickInShape: function (param) {
            return (param.target
                && (param.target.__node
                    || param.target.__route
                    || param.target.__swimlane));
        },
        //鼠标滚轮事件处理
        _mousewheel: function (ev) {
            var self = this;
            var point = [ev.event.zrX, ev.event.zrY];
            var e = (ev || event).wheelDelta;
            if (self.showtype == 1 || self.showtype == 5) {
                self.cancelSel();
                self._mousedown_dragLine();
                self._ckSelectPart(true);
            } else if (self.showtype == 2) {
                //流程跟踪图在显示的时候,使用滚轮会影响下面的流程跟踪信息做一个处理
                //滚轮处理
                if (!self.mwheelEnable) {
                    return;
                }
            }
            // console.log("缩放比例:"+e);
            //设置缩放大小
            self.curDrawLayer.scaleGroup(e > 0 ? 1 : -1, point);
        },
        //在空白处按下鼠标时,如果有拖动路由时,对拖动路由的处理
        _mousedown_dragLine: function () {
            var self = this;
            if (self.dragLineHandler) {
                if (self.dragLineHandler.tmpNode) {
                    self.dragLineHandler.recoveNode(true);
                } else {
                    self.dragLineHandler.removeSelfFromZr();
                }
                self.dragLineHandler = null;
            } else {
                if (self.ckLineObj) {
                    self._unSelectPart();
                }
                self.hideProperties();
            }
        },
        //在空白处按下鼠标时,对区域选择的处理(开始选择,或者是结束选择)
        _mousedown_startsel: function (param) {
            var self = this;
            //开始选择的状态
            self.startSelArea = true;
            if (self.ckSelect) {
                // console.log("................. 开始选择区域");
                //拖动矩形对象已经存在时,显示它并更改坐标和大小
                if (self.dragRectShape) {
                    //已经存在拖动矩形对象时,需要修改矩形位置和大小
                    self.dragRectShape.attr({
                        cursor: 'arrow',
                        shape: {
                            x: param.event.zrX,
                            y: param.event.zrY,
                            width: 0,
                            height: 0
                        }
                    });
                } else {
                    //第一次拖动时,需要创建拖动矩形对象
                    self.dragRectShape = new zRender.Rect({
                        del: false,
                        startPoint: [0, 0],
                        cursor: 'arrow',
                        z: self.curDrawLayer.getZLevel(5),
                        style: {
                            opacity: 0.05,
                            lineWidth: 2,
                            //lineDash:[4 ,2],    //虚线
                            stroke: '#000'
                        },
                        shape: {
                            x: param.event.zrX,
                            y: param.event.zrY,
                            r: 5,
                            //lineDash:[4,2],
                            width: 1,
                            height: 1
                        }
                    });
                }
                //把对象添加到画布中
                self.zrender.add(self.dragRectShape);
            } else {
                self._startDragGroup(param);
            }
        },
        //拖动选择开始标记处理
        _startDragGroup: function (param) {
            var self = this;
            self.startSelArea = true;
            //记录开始位置信息
            self.curDrawLayer.startDrag(param);
        },

        //缩放指定对象
        _doZoom: function (thisObj, zoom, origin) {
            var sc = thisObj.scale[0];
            sc = parseFloat((sc += 0.1 * zoom).toFixed(1));

            if (zoom == 0) {
                sc = 1;
            } else if (sc < 0.1) {
                sc = 0.1;
            }
            thisObj.attr({
                scale: [sc, sc],
                origin: [0, 0]
            });
        },
        //区域选择时,判断节点是否在范围内
        _checkInRect: function () {
            var self = this;
            var rect = this.dragRectShape;
            this.selAreaNodes = [];
            var position = this.curDrawLayer.zrGroup.position;
            $.each(this.curDrawLayer._nodes || [], function (i, node) {
                if (!node) {
                    return self.CONTINUE;
                }
                //在拖动后,由于node的坐标会出现偏移,此处在判断时需要处理
                var x = node.x + position[0];
                var y = node.y + position[1];
                if (rect.rectContain(x, y)
                    && rect.rectContain(x + node.imageWidth, y + node.imageHeight)) {
                    self.selAreaNodes.push(node);
                    node.dragSelected(true);
                } else {
                    node.dragSelected(false);
                }
            });
        },
        //取消区域选择时的处理
        _cancelArea: function () {
            //恢复节点状态
            $.each(this.selAreaNodes || [], function (i, node) {
                if (node) {
                    node.dragSelected(false);
                }
            });
            this.selAreaNodes = [];
            //矩形隐藏
            this.startSelArea = false;
            this._hiddenArea();
        },
        //删除区域选择矩形对象
        _hiddenArea: function () {
            if (this.dragRectShape) {
                // this.dragRectShape = null; //不置为null是为了下次不再创建对象
                this.dragRectShape['del'] = true;
                this.zrender.remove(this.dragRectShape);
            }
        },
        //选择区域拖动时，处理里面的对象位置
        _dragSelArea: function (x, y) {
            var self = this;
            //1.矩形区域位置更改,需要判断边界
            //矩形左顶点，右下角点
            var leftPoint = [self.dragRectShape.shape.x, self.dragRectShape.shape.y];
            //移动开始位置
            var startPoint = self.dragRectShape.startPoint;
            //移动距离
            var posPoint = [x - startPoint[0], y - startPoint[1]];
            //移动后的x，y
            var movePoint = [leftPoint[0] + posPoint[0], leftPoint[1] + posPoint[1]];
            //检测边界
            var lastPoint = self.curDrawLayer.getMinPoint(movePoint);
            //实际移动量
            var point = [lastPoint[0] - leftPoint[0], lastPoint[1] - leftPoint[1]];

            self.dragRectShape.attr({
                startPoint: [x, y],
                shape: {
                    x: lastPoint[0],
                    y: lastPoint[1]
                }
            });
            //2.里面对象位置更改
            $.each(self.selAreaNodes, function (i, node) {
                if (!node) {
                    return self.CONTINUE;
                }
                node.posNode(point[0], point[1]);
            });
        },

        //隐藏属性显示框
        hideProperties: function () {
            // $(this.container).find('.fd-main').removeClass('other-property-show other-property-content-show');
            this.zrender.resize();
        },
        //撤销路由选中状态
        _unSelectPart: function () {
            var self = this;
            if (self.ckLineObj) {
                self.ckLineObj.removeClass("selected");
                self.ckLineType = null;
                self.ckLineObj = null;
            }
        },
        //撤销/隐藏所有选中的状态(菜单,浮动显示,选中的节点,选中的路由,选中的泳道)
        cancelSel: function () {
            var self = this;
            self._hideContextMenu();
            self.hideTitle();

            if (self.selLineHandler) {
                self.selLineHandler.cancelSel();
            }

            if (self.selNodeHandler) {
                self.selNodeHandler.cancelSel();
            }
            if (self.selSwimlaneHandler) {
                self.selSwimlaneHandler.cancelSel();
            }
        },

        //显示浮动提示标题,主要用于节点/路由/泳道的文字显示
        showTitle: function (text, eventPosition) {
            var $title = this.tooltipTxt;

            var left = eventPosition.x + 10,
                top = eventPosition.y + 15;
            var width = this.zrender.getWidth();
            if (width - eventPosition.x < 125) {
                left -= (125 - (width - eventPosition.x));
            }
            $title.css({
                left: left,
                top: top
            }).html(text).show();
        },
        //隐藏浮动提示显示
        hideTitle: function () {
            this.tooltipTxt.hide();
        },
        //工具栏中的选择图标选中和取消处理
        _ckSelectPart: function (hide) {
            if (this.curDrawLayer.isScale()) {
                return;
            }
            var $this = this.ckPartObj;
            if ($this) {
                if ($this.hasClass('selected')) {
                    $this.removeClass('selected');
                    this.ckSelect = false;
                } else if (!hide) {
                    $this.addClass('selected');
                    this.ckSelect = true;
                }
            }
        },

        //=============流程跟踪图中的动态演示处理============================
        _dynamicDemo: function () {
            var self = this;
            var historys = this.data.historys;
            //创建移动的对象
            var _nodes = self.curDrawLayer._nodes;
            var _lines = self.curDrawLayer.tmpRoutes;
            var jumpNodes = this.data.runData['JumpNodes'] || '';
            var movePath = [];
            $.each(historys || [], function (i, history) {
                if (!history) {
                    return self.CONTINUE;
                }
                var node = history["nodeid"];
                var nxtNodeids = history["nextnodeids"].split(";");
                var nodePoints = [];
                $.each(nxtNodeids || [], function (i, nxtid) {
                    if (nxtid && nxtid != node) {
                        //查找对应的路由
                        var line = _lines[node + "_" + nxtid];
                        var points = [];
                        if (line) {
                            points = line.points;
                        } else {
                            //没有路由的情况
                            var start = _nodes[node];
                            var end = _nodes[nxtid];
                            points = self._makeVirtualPath(start, end, history['action'], jumpNodes);
                        }
                        nodePoints.push(points);
                    }
                });
                if (nodePoints.length > 0) {
                    movePath.push(nodePoints);
                }
            });
            var group = new zRender.Group();
            this.curDrawLayer.zrGroup.add(group);
            self._doMove(group, movePath, 0, movePath.length);
        },
        _makeVirtualPath: function (start, end, action, jumpNodes) {
            //没有直接路由,有以下几种可能
            //1.有虚拟节点时
            //2.跳转时
            //3.跳过节点时 //需要判断路由经过节点状态从节点的data.showtype中获取
            /*
            //只要不是提交操作,都是直接返回两点
            if(action.toLowerCase() != 'submit'){
                return this._backTwoPoint(start,end);
            }
            //首先判断end节点前面是否有虚拟节点
            var virtual = this._checkFrontIsVirtual(end);
            if(virtual){
                //如果有虚拟节点时,从start到virtual,再到end
                points.push({
                    x: start.x + start.imageWidth / 2,
                    y: start.y + start.imageHeight / 2
                });
                //中间插入虚拟节点的坐标
                points.push({
                    x: virtual.x + virtual.imageWidth / 2,
                    y: virtual.y + virtual.imageHeight / 2
                });
                points.push({
                    x: end.x + end.imageWidth / 2,
                    y: end.y + end.imageHeight / 2
                });
                return points;
            }
            //判断是否跳过时的情况

            if(this._getPathByRoute(points,start,end)) {
                points.reverse();
                //把二维数组变成一维数组(是否需要去掉重复的点呢?需要看后面)
                var tPoints = [];
                $.each(points || [],function(i,point){
                    $.each(point || [],function(i,p){
                        tPoints.push(p);
                    })
                })
                points = tPoints;
            }
            else{
                //没有出口路由时,肯定执行的是跳转
                return this._backTwoPoint(start,end);
            }
            return points;

            //*/

            var points = this._checkPath(start, end, jumpNodes);
            if (points.length == 0) {
                return this._backTwoPoint(start, end);
            }

            //把二维数组变成一维数组(是否需要去掉重复的点呢?需要看后面)
            var tPoints = [];
            $.each(points || [], function (i, point) {
                $.each(point || [], function (i, p) {
                    tPoints.push(p);
                })
            });

            return tPoints;
        },
        //确定从start到end之间的路由关系,只有在start和end没有直接路由连接时处理
        //从end反向往上查找,1.如果有虚拟则直接结束,2.如果有跳过则继续往上,否则直接两点连接
        _checkPath: function (start, end, jumpNodes) {
            var self = this;
            var _lines = this.curDrawLayer.tmpRoutes;
            var virtual = this.options.nodetype['Node_Virtual']['data'];

            var points = [];
            //获取end的所有指向路由列表
            var lines = this._getFromLines(end, _lines);
            //判断所有指向节点,优先返回开始节点,虚拟节点,其他
            var tmpLine;
            $.each(lines, function (key, line) {
                if (line) {
                    if (line.fromNode == start) {
                        tmpLine = line;
                        return self.BREAK;
                    }
                    //如果有虚拟节点时,也可能有直接节点,所以不能直接结束
                    if (line.fromNode.nodetype == virtual) {
                        tmpLine = line;
                    }
                }
            });
            if (tmpLine) {
                if (tmpLine.fromNode == start) {
                    points.push(tmpLine.points);
                } else if (tmpLine.fromNode.nodetype == virtual) {
                    //如果有虚拟节点则结束
                    //增加开始节点到虚拟节点的路径
                    points.push(self._backTwoPoint(start, tmpLine.fromNode));
                    points.push(tmpLine.points);
                }
            } else {
                $.each(lines, function (key, line) {
                    if (!line) {
                        return self.CONTINUE;//continue;
                    }
                    if (jumpNodes.indexOf(line.fromNode.id + ';') != -1) {
                        //往上递归
                        var result = self._checkPath(start, line.fromNode, jumpNodes);
                        if (result.length > 0) {
                            $.each(result, function (i, tmp) {
                                points.push(tmp);
                            });
                        }

                        //如果上一节点有跳过的节点,继续往上查找
                        points.push(line.points);
                        return self.BREAK;
                    }

                });
            }

            return points;
        },

        //获取node的指向路由列表
        _getFromLines: function (node, _lines) {
            var lines = [];
            $.each(_lines, function (key, line) {
                if (line && line.toNode == node) { //应该时同一个对象吧
                    lines.push(line);
                }
            });
            return lines;
        },
        _backTwoPoint: function (start, end) {
            var points = [];
            points.push({
                x: start.x + start.imageWidth / 2,
                y: start.y + start.imageHeight / 2
            });
            points.push({
                x: end.x + end.imageWidth / 2,
                y: end.y + end.imageHeight / 2
            });
            return points;
        },

        _doMove: function (group, movePath, pos, len) {
            var self = this;
            var nowPaths = movePath[pos] || [];
            $.each(nowPaths, function (i, nowPath) {
                if (!nowPath) {
                    return self.CONTINUE;
                }
                var img = self._createNewMoveImg(group);//,nowPath[nowPath.length-1],tmpImg);//

                self._addAnimate(img, nowPath).start().done(function () {
                    setTimeout(function () {
                        group.remove(img); //删掉当前圆点
                    }, 500);

                    if (i == 0) {
                        setTimeout(function () {
                            self._doMove(group, movePath, pos + 1, len);
                        }, 500);
                    }
                });
            });

        },

        _createNewMoveImg: function (group) {
            var color = this.options.flownode.color.now;
            var img = new zRender.Circle({
                z: 10,
                style: {
                    stroke: color,
                    fill: color,
                    opacity: '1'
                },
                position: [0, 0],
                shape: {
                    cx: 0,
                    cy: 0,
                    r: 6
                }
            });

            group.add(img);
            return img;
        },
        _addAnimate: function (img, points) {
            //增加动画路径
            var len = points.length;
            var stay = parseInt(1000 / (len - 1));
            var dyImg = img.animate('position', false);
            stay = stay < 200 ? 200 : stay;
            //如果第一个点和第二个点在同一水平线或者同一垂直线时,也就是x或者y相同时,会出现点位置不对(=0)
            //只有直线的时候会出现这种情况,折线不会出现
            if (len == 2) {
                var point1 = points[0];
                var point2 = points[1];
                if (point1.x == point2.x) {
                    point1.x += 1;
                }
                if (point1.y == point2.y) {
                    point1.y += 1;
                }
            }
            for (var i = 0; i < len; i++) {
                dyImg = dyImg.when(i * stay, [points[i].x, points[i].y]);
            }
            return dyImg;
        },

        _saveLogImg: function () {
            var point = {
                width: this.zrender.getWidth(),
                height: this.zrender.getHeight()
            };
            this.curDrawLayer.restoreAll();//恢复大小
            var mxPoint = this.curDrawLayer.maxPoint;
            //mxPoint 可能为0,0,需要处理
            if (mxPoint[0] == 0 || mxPoint[1] == 0) {
                mxPoint = [this.curDrawLayer.rectPoint['maxX'], this.curDrawLayer.rectPoint['maxY']];
            }

            this.zrender.resize({
                width: mxPoint[0],
                height: mxPoint[1]
            });

            var imgURL = this.zrender.painter._domRoot.firstChild.toDataURL('image/png');
            this.zrender.resize(point);

            imgURL = imgURL.replace("image/png", "image/octet-stream");
            var date = new Date();
            var m = '0' + date.getMonth();
            var d = '0' + date.getDay();
            var _twoChartStr = function (str) {
                var ss = '0' + str;
                return ss.substring(ss.length - 2);
            }
            var name = this.getLang('static.logImgName') + date.getFullYear() + _twoChartStr(date.getMonth() + 1)
                + _twoChartStr(date.getDate()) + _twoChartStr(date.getHours())
                + _twoChartStr(date.getMinutes()) + _twoChartStr(date.getSeconds())
                + '.png';
            this._saveImageToLocal(name, imgURL);
        },
        _showAllHistory: function () {
            var self = this;
            var title = this.getLang('static.allhistory');
            if (self.data['title']) {
                title = '[' + (self.data['title'] || '') + ']' + title;
            }
            this.popSelWin(
                title,
                '<table id="popSel" />',
                function () {
                },
                '830px', null, function ($this) {
                    $this.$contentPane.css('max-height', '450px');
                    var items = self.data['historys'] || [];
                    self.makeHistoryTable($this, items);
                });
        },
        _menuWheel: function () {
            this.mwheelEnable = !this.mwheelEnable;
        },
        //===============当前主菜单选项生成===========================
        //生成菜单选项,并显示
        _showFlowMenu: function (param) {
            var self = this;
            var para = {};
            para.left = param.event.zrX;
            para.top = param.event.zrY;
            para.items = [];
            switch (self.showtype) {
                case 1:
                case 5:
                    self._showFlowMenu_Designer(para);
                    break;
                case 2:
                    self._showFlowMenu_Tracklog(para);
                    break;
                case 3:
                    self._showFlowMenu_Monitor(para);
                    break;
                case 4:
                    self._showFlowMenu_AutoTest(para);
                    break;
                case 7:
                    self._showFlowMenu_Restore(para);
                    break;
                case 8:
                    self._showFlowMenu_GeneralDesigner(para);
                    break;
                case 9:
                    self._showFlowMenu_GeneralShow(para);
            }

            para.layer = self.curDrawLayer;
            this.showContextMenu(para, true);
        },
        _showFlowMenu_Designer: function (para) {
            var self = this;
            var show = (this.selAreaNodes.length > 1);
            var isSub = false;
            if (self.curDrawLayer.parentFlowid) {
                isSub = true;
                para.items.push(
                    {
                        text: self.getLang('menu.back') + self.curDrawLayer.parentFlowid,
                        target: this,
                        fun: '_backMainCanvas'
                    });
                para.items.push(
                    {
                        text: '-',
                        enable: false
                    });
            }

            para.items.push(
                {
                    text: self.curDrawLayer.flowid + ' ' + this.getLang('menu.flowpro'),//属性设置
                    target: this,
                    fun: '_showProperties',
                    para: 1
                });
            para.items.push(
                {
                    text: this.getLang('menu.savelocal'),//'保存到本地',
                    fun: function () {
                        self._saveToLocal();
                    }
                });
            para.items.push(
                {
                    text: this.getLang('menu.saveserver'),//'保存到服务器',
                    target: this,
                    fun: '_saveToServer',
                    para: 1
                });
            para.items.push(
                {
                    text: this.getLang('menu.openlocal'),//'从本地打开',
                    enable: (!isSub),
                    target: this,
                    fun: '_openLocalFile'
                });
            if (self.showtype == 1) {
                para.items.push(
                    {
                        text: this.getLang('menu.copy'),//'复制此流程',
                        enable: (!isSub),
                        target: this,
                        fun: '_copydata',
                        para: null
                    });
            }
            para.items.push(
                {
                    text: '-',
                    enable: false
                });

            para.items.push(
                {   //'允许拖动/禁止选择':'禁止拖动/允许选择',
                    text: self.ckSelect ? this.getLang('menu.drag') : this.getLang('menu.select'),
                    enable: !self.curDrawLayer.isScale(),
                    target: self,
                    fun: '_ckSelectPart'
                }
            );

            self._showFlowMenu_Restore(para);
            para.items.push(
                {
                    text: self.getLang('static.logImgName'),
                    fun: function () {
                        self._saveLogImg();
                    }
                });
            if (!self.curDrawLayer.isScale()) {
                para.items.push(
                    {
                        text: '-',
                        enable: false
                    });
                para.items.push(
                    {
                        text: this.getLang('menu.addswim'),//'添加泳道',
                        target: this,
                        fun: '_swimlanes'
                    });
                para.items.push(
                    {
                        text: this.getLang('menu.left'),//'左对齐',
                        enable: show,
                        fun: function () {
                            self._chgAlignNode(true, true);
                        }
                    });
                para.items.push(
                    {
                        text: this.getLang('menu.right'),//'右对齐',
                        enable: show,
                        fun: function () {
                            self._chgAlignNode(true, false);
                        }
                    });
                para.items.push(
                    {
                        text: this.getLang('menu.top'),//'上对齐',
                        enable: show,
                        target: this,
                        fun: function () {
                            self._chgAlignNode(false, true);
                        }
                    });
                para.items.push(
                    {
                        text: this.getLang('menu.bottom'),//'下对齐',
                        enable: show,
                        fun: function () {
                            self._chgAlignNode(false, false);
                        }
                    });
            }
            para.items.push(
                {
                    text: '-',
                    enable: false
                });
            para.items.push(
                {
                    text: self.curDrawLayer.flowid + ' ' + self.getLang('menu.showdata'),//属性设置
                    fun: function () {
                        self.showJsonData(self.curDrawLayer.data);
                    }
                });
            para.items.push(
                {
                    text: this.getLang('menu.refresh'),//'刷新页面',//属性设置
                    target: this,
                    fun: '_refreshThisPage'
                });
            if (self.showtype == 1) {
                //只有主流程才可以打开历史版本
                if (self.flowid == self.curDrawLayer.flowid) {
                    para.items.push(
                        {
                            text: '-',
                            enable: false
                        });
                    para.items.push(
                        {
                            text: self.getLang('menu.hisver'),//'历史版本',//属性设置
                            fun: function () {
                                self._openFlowVer();
                            }
                        });
                }
                para.items.push(
                    {
                        text: '-',
                        enable: false
                    });
                para.items.push(
                    {
                        text: self.getLang('menu.testflow'),//'测试流程',//属性设置
                        fun: function () {
                            self._testFlow(1);
                        }
                    });
                para.items.push(
                    {
                        text: self.getLang('menu.autotest'),//'自动测试',//属性设置
                        fun: function () {
                            self._testFlow(2);
                        }
                    });
            }

        },
        _showFlowMenu_Tracklog: function (para) {
            var self = this;
            para.items.push({
                text: this.getLang('menu.history'),
                target: this,
                fun: '_showAllHistory'
            });
            para.items.push({
                text: this.getLang('menu.dynamic'),//'动态演示',
                target: this,
                fun: '_dynamicDemo'
            });//'动态演示',
            para.items.push({
                text: this.getLang('menu.saveimg'),//'截图',
                target: this,
                fun: '_saveLogImg'
            });
            para.items.push({
                text: '-',
                enable: false
            });
            var sh = this.getLang('menu.mousewheel').split(',');
            para.items.push({
                text: sh[self.mwheelEnable ? 1 : 0],//'截图',
                target: this,
                fun: '_menuWheel'
            });
            para.items.push({
                text: '-',
                enable: false
            });
            self._showFlowMenu_Restore(para);
        },
        _showFlowMenu_Monitor: function (para) {
            var self = this;
            if (this.curDrawLayer.parentFlowid) {
                para.items.push(
                    {
                        text: this.getLang('menu.back') + ' ' + this.curDrawLayer.parentFlowid,
                        target: this,
                        fun: '_backMainCanvas'
                    });
                para.items.push(
                    {
                        text: '-',
                        enable: false
                    });
            }
            //如果有额外节点数据时,需要显示出来
            if (Object.keys(this.curDrawLayer['aloneNodes']).length > 0) {
                para.items.push(
                    {
                        text: this.getLang('menu.alone'),
                        target: this,
                        fun: '_showAloneNodes'
                    });
                para.items.push(
                    {
                        text: '-',
                        enable: false
                    });
            }

            self._showFlowMenu_Restore(para);
        },
        _showFlowMenu_AutoTest: function (para) {
            var self = this;
            para.items.push(
                {
                    text: this.getLang('menu.restart'),//'重新开始',
                    target: self,
                    fun: '_reAutoTest',
                    para: null
                });

            self._showFlowMenu_Restore(para);
        },
        _showFlowMenu_Restore: function (para) {
            var self = this;
            para.items.push(
                {   //'原大小'
                    text: this.getLang('menu.original') + self.curDrawLayer.getScale(),
                    enable: self.curDrawLayer.isScale(),
                    target: self.curDrawLayer,
                    fun: 'restoreScale',
                    para: null
                });
            para.items.push(
                {   //'回到原点'
                    text: this.getLang('menu.zero') + self.curDrawLayer.getPosition(),
                    enable: self.curDrawLayer.isPosition(),
                    target: self.curDrawLayer,
                    fun: 'restoreDrag',
                    para: null
                }
            );
            para.items.push(
                {
                    text: this.getLang('menu.start'),//'初始位置大小',
                    enable: self.curDrawLayer.isPosition() || self.curDrawLayer.isScale(),
                    target: self.curDrawLayer,
                    fun: 'restoreAll',
                    para: null
                }
            );

            if (!(self.showtype == 1 || self.showtype == 5)) {
                para.items.push({
                    text: '-',
                    enable: false
                });
                para.items.push({
                    text: self.version,
                    enable: false
                });
            }

        },
        _showFlowMenu_GeneralDesigner: function (para) {
            var self = this;
            para.items.push(
                {
                    text: this.getLang('menu.flowpro'),//属性设置
                    target: this,
                    fun: '_showGeneralProperties',
                    para: 1
                });

            self._showFlowMenu_Restore(para);
        },
        _showFlowMenu_GeneralShow: function (para) {
            var self = this;
            self._showFlowMenu_Restore(para);
        },

        //===========菜单创建/显示/关闭(节点路由菜单调用)====================
        //显示菜单对象,并计算处理显示位置,以及是否阻止冒泡处理
        showContextMenu: function (param, show) {
            if (param.items.length == 0) {//没有菜单项时
                return;
            }
            if (!show && param.layer) {
                if (param.layer.isScale()) {
                    return;
                }
            }
            var $contextMenu = this.menuContainer;
            var $ul = this._makeMenuItem(param.items);
            $contextMenu.html("");
            $contextMenu.append($ul);
            var maxHeight = this.zrender.getHeight(),
                maxWidth = this.zrender.getWidth() - 20,
                menuHeight = $contextMenu.outerHeight(),
                menuWidth = $contextMenu.outerWidth();
            var left = (param.left + menuWidth) > maxWidth ? (param.left - menuWidth) : param.left,
                top = (param.top + menuHeight) > maxHeight ? (param.top - menuHeight) : param.top;
            if (left < 1) {
                left = 1;
            }
            //20200407 LIYS 调整菜单位置显示
            if (top < -66) {
                top = -66;
            }

            $contextMenu.css({
                width: 200,
                left: left,
                top: top
            }).show();

            if (param.event) {
                param.event.cancelBubble = true;//阻止继续冒泡
            }
        },
        //隐藏菜单显示
        _hideContextMenu: function () {
            this.menuContainer.hide();
        },
        //生成菜单选项
        _makeMenuItem: function (items) {
            var self = this;
            var ul = $('<ul>');
            $.each(items || [], function (i, item) {
                if (!item) {
                    return self.CONTINUE;
                }
                if (item.enable || item.enable == undefined) {
                    var li = $('<li></li>');
                    var a = $('<a href="javascript:">' + item.text + '</a>');
                    a.on('click', function () {
                        self._hideContextMenu();
                        if (typeof item.fun == 'string') {
                            item.target[item.fun](item.para);
                        } else {
                            item.fun();//fun中不能有this,否则会指向不明
                        }
                    });
                    li.append(a);
                    ul.append(li);
                } else if (item.text == '-') {
                    ul.append('<hr/>');
                } else {
                    ul.append('<span>' + item.text + '</span><br>');
                }
            });
            return ul;
        },

        //===============画布变化时的处理(清空,子流程显示/返回)==================
        //清空画布时的数据初始化
        _initCanvas: function () {
            var self = this;
            var mainLayer = this.drawLayers[this.dataid];
            //删除当前层
            self._clearZrender();
            if (mainLayer) {
                this.drawLayers = {};
                this.drawLayers[this.dataid] = mainLayer;
                mainLayer.clearCanvas();

                this.curDrawLayer = mainLayer;
                this.zrender.add(mainLayer.zrGroup);
            }
        },
        //初始化画图需要用到的临时数据
        _initTmpData: function () {
            this.selLineHandler = null;
            this.selNodeHandler = null;
            this.selSwimlaneHandler = null;
            this.dragLineHandler = null;
            this.tmpImgShapeForSub = null;
        },
        //子流程数据显示,
        _showSubFlow: function (data, subLayer, subnode) {
            var self = this;
            var layerShow = true;   //是否层叠显示
            if (layerShow) {
                //如果需要显示父流程时,把流程转换为图片,避免事件
                self._showCanvasToImg(true);
            }
            self.zrender.remove(self.curDrawLayer.zrGroup);
            self._ckSelectPart(true);
            var showRect = self.showtype == 3; //在流程监控时显示矩形包围框

            // 子流程数据是从后台重新获取的,应该比现有子流程节点上的数据新
            // 把数据更新到子流程节点上的数据中
            /*
              {
               nodeid:xxx,
               nodename:xxx,
               sumnum:0,
               subflows:[],
               (subflowid):{}
              }
             */
            // nodeid 子流程节点,flowid 节点(nodeid)上的子流程,
            // newnum为nodeid上的子流程flowid的实例数
            var recursiveChgParentData = function (node, flowid, newnum, warnnum) {
                //子流程节点上的原有数据(用newnum,warnnum来更新)
                var oldnum = node.data[flowid]['sumnum'];  // 说明总数变化
                var oldwarn = node.data[flowid]['warnnum'] || 0; //警告数变化(可能为undefined)

                if (oldnum != newnum || oldwarn != warnnum) {
                    //数据有变化时的处理
                    var total = node.data['sumnum'];        // 总数是肯定要有的
                    var wnum = node.data['warnnum'] || 0;   // 0 说明子流程节点上本来是没有警告数据的,

                    total = total - oldnum + newnum;
                    node.data['sumnum'] = total;    //总数修改

                    if (warnnum != 0) {
                        wnum = wnum - oldwarn + warnnum;
                        node.data['warnnum'] = wnum;
                    }

                    //修改图形显示
                    node.chgInstanceNum(total, wnum);
                    node.data[flowid]['sumnum'] = newnum; //对应的子流程数修改
                    node.data[flowid]['warnnum'] = warnnum; //对应的子流程数修改

                    //继续往上更新
                    var parentNodeid = node.__drawLayer.parentNodeid;
                    var parentFlowid = node.__drawLayer.parentFlowid;
                    if (parentNodeid && parentFlowid) {
                        // 获取到父节点的层对象
                        var parentLayer = self.drawLayers[parentFlowid];
                        var parentNode = parentLayer._nodes[parentNodeid];

                        recursiveChgParentData(parentNode, node.__drawLayer.flowid, total, wnum);
                    }
                }
            };
            var chgParentData = function (data, node, flowid) {
                //data是flowid子流程的数据,node是子流程所在的节点(父流程上的子流程节点)
                var newnum = data['instanceNums']['sumnum'];
                var warnnum = data['instanceNums']['warnnum'] || 0;
                //修改父节点的数据
                recursiveChgParentData(node, flowid, newnum, warnnum);
                //替换
                node.data[flowid] = data['instanceNums'];
            };
            //子流程已经加载过时subLayer不为空
            if (subLayer) {
                if (showRect && data && data['instanceNums']) {
                    //更新节点上的数据
                    $.each(subLayer._nodes, function (nodeid, node) {
                        if (!node) {
                            return self.CONTINUE;
                        }
                        node.data = data['instanceNums'][nodeid];
                        var num = '0', warn = '0';
                        if (node.data) {
                            num = node.data['sumnum'];
                            warn = node.data['warnnum'] || '0'; //这个可能会没有
                        }

                        node.chgInstanceNum(num, warn);
                    });

                    //修改父节点的数据
                    chgParentData(data, subnode, subLayer.flowid);
                }
                if (subLayer.minZ < self.curDrawLayer.minZ) {
                    //如果要显示的子流程层高小于当前层,则说明出现循环
                    //此时把所有的都清空,回到初始状态
                    if (self.tmpImgShapeForSub) {
                        self.zrender.remove(self.tmpImgShapeForSub);
                    }

                    self._initTmpData();
                    showRect = false;
                }
                //流程之间互相子流程时,只需要显示已经存在的数据就可以了
                subLayer.parentFlowid = self.curDrawLayer.flowid;
                subLayer.parentNodeid = subnode.id;
                if (showRect) {
                    // 在流程监控图是显示一个矩形包围框
                    subLayer.rectShape.show();
                }
                //添加子流程图到容器中(显示子流程图)
                self.zrender.add(subLayer.zrGroup);

                // 当出现循环时(主流程作为子流程再次打开时),
                // 如果主流程(第二次打开时)继续点击子流程,则清空主流程的上级流程信息
                // 避免返回时,出现中断回不到主流程的情况
                if (self.curDrawLayer.isMain && self.curDrawLayer.parentFlowid) {
                    self.curDrawLayer.parentFlowid = null;
                    self.curDrawLayer.parentNodeid = null;
                }
                subLayer.maskRectShape.hide();
            } else {
                //从服务器上加载数据后
                var subflowid = data.mapData.flowId;
                //创建一个新的数据层
                subLayer = new DrawLayer(self, subflowid);
                //强制从后端重新加载数据时,记录一下原来的层数
                var oldSublayer = self.drawLayers[subflowid];
                var minZ = 0;
                if (oldSublayer) {
                    minZ = oldSublayer.minZ;
                }
                //赋值新创建的层来替换原来的层对象(不使用更新旧对象的方法,那样还需要清空对象)
                self.drawLayers[subflowid] = subLayer;

                subLayer.parentFlowid = self.curDrawLayer.flowid;
                subLayer.parentNodeid = subnode.id;

                //如果不层叠显示,则不需要分层处理
                if (layerShow) {
                    //层叠显示
                    var len = Object.keys(self.drawLayers).length;
                    subLayer.minZ = minZ == 0 ? (len * 10) : minZ;
                }
                // 解析数据并恢复图形显示
                self._parseData(subLayer, data);

                if (showRect) {
                    subLayer.rectShape.show();
                    subLayer.refreshRect(true);

                    //修改父节点的数据
                    chgParentData(data, subnode, subLayer.flowid);
                }
            }
            if (showRect) {
                //移动到中心位置
                //获取中心点坐标
                var x = self.zrender.getWidth() / 2,
                    y = self.zrender.getHeight() / 2;
                var center = subLayer.getCenterPoint();
                subLayer.zrGroup.attr({
                    position: [x - center[0], y - center[1]]
                });
            } else if (self.showtype == 1 || self.showtype == 5) {
                //流程定义或者实例定义修改时,切换状态栏信息
                self._chgStatusTitle(subLayer.data['flowInfo']);
            }
            //在即将要显示的层中记录其背景图片数据
            if (self.tmpImgShapeForSub) {
                subLayer.backimg = self.tmpImgShapeForSub.style.image;
            }
            //重新设置当前层
            self.curDrawLayer = subLayer;
        },
        //把当前画布转换为图形显示,避免事件相应
        _showCanvasToImg: function (show) {
            var self = this;
            if (show) {
                //获取背景图片
                //根据showtype处理背景图片,
                //showtype=1时,在主流程上增加一个半透明的矩形
                //showtype=3时,不处理,子流程层的包围框显示
                var tmpRect = null;
                if (self.showtype == 1) {
                    self.curDrawLayer.maskRectShape.attr({
                        z: self.curDrawLayer.getZLevel(self.zArr.selected + 1)
                    });
                    self.curDrawLayer.maskRectShape.show();
                    self.zrender.refreshImmediately();
                }
                var imgURL = self.zrender.painter._domRoot.firstChild.toDataURL();
                self._showTmpImgShapeForSub(imgURL);
            } else {
                self._makeTmpImgShapeForSub();
                self.tmpImgShapeForSub.hide();
            }
        },
        //更新显示临时背景图片
        _showTmpImgShapeForSub: function (imgURL) {
            var self = this;
            self._makeTmpImgShapeForSub();
            self.tmpImgShapeForSub.attr({
                style: {
                    image: imgURL
                }
            });
            self.tmpImgShapeForSub.show();
        },
        //创建一个临时image对象,用来显示背景(上级主流程图)
        _makeTmpImgShapeForSub: function () {
            var self = this;
            var opacity = self.options['subOpacity'];
            opacity = opacity[opacity.length - 1];
            if (!self.tmpImgShapeForSub) {
                //不存在时,创建新的对象并添加到画布中
                self.tmpImgShapeForSub = new zRender.Image({
                    z: 0,
                    style: {
                        opacity: opacity,
                        x: 0,
                        y: 0,
                        width: self.zrender.getWidth(),
                        height: self.zrender.getHeight(),
                        image: ''
                    }
                });
                self.tmpImgShapeForSub.hide();//默认隐藏
                self.zrender.add(self.tmpImgShapeForSub);
            }
        },
        //返回上级流程
        _backMainCanvas: function () {
            var self = this;
            var mainLayer = self.drawLayers[self.curDrawLayer.parentFlowid];
            if (mainLayer) {
                // 一)隐藏背景图片,隐藏包围框,隐藏遮罩层,
                // 为了重新建立一个当前层图形作为主流程子流程节点的背景图片使用
                // 1.隐藏临时图片
                if (self.tmpImgShapeForSub) {
                    self.tmpImgShapeForSub.hide();
                }
                //2.隐藏包围框
                self.curDrawLayer.rectShape.hide();//不显示包围框
                //3.隐藏遮罩层
                self.curDrawLayer.maskRectShape.hide();
                //4.恢复到原大小位置
                self.curDrawLayer.restoreAll();
                //5.让隐藏立即生效,否则下面的toDataURL不能正确获取
                self.zrender.refreshImmediately();//如果不立即刷新,下面的图片会显示出临时图
                //6.获取图形图片数据
                var imgURL = self.zrender.painter._domRoot.firstChild.toDataURL();
                //7.把上面获取的子流程图形缩小为图片显示在主流程中
                mainLayer._nodes[self.curDrawLayer.parentNodeid]
                    .makeNewImg(imgURL, self.curDrawLayer.rectPoint);
                //二)清空当前层的背景图片(子流程层)
                self.curDrawLayer.backimg = null;
                self.curDrawLayer.parentFlowid = null;
                self.curDrawLayer.parentNodeid = null;
                //三)从画布中删除当前层的图形
                self.zrender.remove(self.curDrawLayer.zrGroup);
                //四)恢复上级流程的背景图片
                if (mainLayer.backimg) {
                    self._showTmpImgShapeForSub(mainLayer.backimg);
                }
                //五)主层的遮罩层隐藏
                mainLayer.maskRectShape.hide();
                //六)把上级流程图形添加到画布中
                self.zrender.add(mainLayer.zrGroup);
                //七)重新设置当前层
                self.curDrawLayer = mainLayer;
                if (self.showtype == 1 || self.showtype == 5) {
                    //流程定义或者实例定义修改时,切换状态栏信息
                    self._chgStatusTitle(mainLayer.data['flowInfo']);
                }
            } else {
                $.confirm({
                    title: self.getLang('static.info'),
                    content: self.getLang('static.mainisnull'),
                    type: 'red',
                    icon: 'glyphicon glyphicon-info-sign',
                    buttons: {
                        ok: {
                            text: this.getLang('static.ok'),
                            btnClass: 'btn-primary',
                            action: function () {
                            }
                        }
                    }
                });
            }
        },

        //清理画布图层
        _clearZrender: function () {
            //删除当前层的图形
            this.zrender.remove(this.curDrawLayer.zrGroup);
            //删除临时图形
            if (this.tmpImgShapeForSub) {
                this.zrender.remove(this.tmpImgShapeForSub);
            }
        },

        //============工具栏图标的点击响应处理======================
        //响应拷贝处理
        //文件菜单点击
        _ckFile: function () {
            var self = this;
            var title = this.getLang('parts');
            var para = {};
            var pos = this.options['fileMenuPos'] || [12, -6];
            para.left = pos[0];
            para.top = pos[1];
            para.items = [];
            if (this.showtype == 1) {
                para.items.push(
                    {
                        text: title['new'],//新建
                        target: this,
                        fun: '_creatNewFlow'
                    });
                para.items.push(
                    {
                        text: title['openserver'],//从服务器上打开
                        target: this,
                        fun: '_openFromServer'
                    });
            }
            para.items.push(
                {
                    text: title['openlocal'],//打开本地
                    target: this,
                    fun: '_openLocalFile'
                });


            para.items.push(
                {
                    text: '-',
                    enable: false
                });

            para.items.push(
                {
                    text: title['savelocal'],//保存到本地
                    target: this,
                    fun: '_saveToLocal'
                });
            para.items.push(
                {
                    text: title['saveserver'],//保存到服务器上
                    target: this,
                    fun: '_saveToServer',
                    para: 1
                });
            if (this.showtype == 1) {
                para.items.push(
                    {
                        text: title['savenewver'],//保存到新版本到服务器上
                        target: this,
                        fun: '_saveToServer',
                        para: 2
                    });
                para.items.push(
                    {
                        text: title['saveoldver'],//保存到服务器上(版本不变)
                        target: this,
                        fun: '_saveToServer',
                        para: 3
                    });
                para.items.push(
                    {
                        text: '-',
                        enable: false
                    });
                para.items.push(
                    {
                        text: title['copy'],//复制流程
                        target: this,
                        fun: '_copydata'
                    });
                para.items.push(
                    {
                        text: title['nodemodule'],//节点模版列表
                        target: this,
                        fun: '_openNodeModuleLst'
                    });
                para.items.push(
                    {
                        text: '-',
                        enable: false
                    });

            }

            para.layer = self.curDrawLayer;
            this.showContextMenu(para, true);
        },
        _openNodeModuleLst: function () {
            var self = this;
            var title = this.getLang('nodemodule');
            //['节点模版列表','模版数据异常','删除成功!','请选择要删除的模版','删除','关闭'];
            self.getNodeModuleLstFromServer('', function (data) {
                var nodes = data && data.nodes || {};
                var zNodes = self.initTreeData(nodes);
                var html =
                    '<div style="background-color: #F5F5F5">' +
                    '<ul id="tree" class="ztree" style="width:300px;height:300px; overflow:auto;"></ul></div>' +
                    '<div style="display: block;position: absolute;margin-left: 305px;top: 0px">' +
                    '<select name="moduleId" size=10 style="width:215px;height:300px;" multiple></select>' +
                    '</div>';

                var initPopHtml = function ($content) {
                    //初始化树
                    $content.find("#tree").html("");
                    $.fn.zTree.init($content.find("#tree"), {
                        callback: {
                            onClick: function (event, treeId, treeNode) {
                                initSelect(treeNode.data);
                            }
                        }
                    }, zNodes);
                    var initSelect = function (data) {
                        //初始化所有数据到列表中
                        var moduleId = $content.find('select[name="moduleId"]');
                        moduleId.empty();
                        $.each(data || [], function (i, item) {
                            if (item) {
                                moduleId.append('<option value="' + item.id + '">' + item.name + '</option>');
                            }
                        });
                    };
                    //默认显示全部
                    initSelect(nodes);
                }

                self.popSelWin(title[0], html,
                    function ($this) {
                        var selObj = $this.find('select[name="moduleId"]');
                        var allsel = selObj.val();
                        if (!allsel || allsel.length == 0) {
                            self.showMsg(title[3]);
                            return false;
                        }
                        //记录模版ID和ruleId
                        var mId = '';
                        var rId = '';
                        var back = false;
                        $.each(allsel, function (i, id) {
                            var nodeObj = nodes[id];
                            if (nodeObj && nodeObj['data']) {
                                var node = JSON.parse(nodeObj['data']);
                                var ruleId = node['ruleId'];
                                mId += ',' + id;
                                if (ruleId) {
                                    rId += ',' + ruleId;
                                }
                            } else {
                                self.showMsg(title[1]);
                                back = true;
                                return self.BREAK;
                            }
                        });
                        if (back) {
                            return;
                        }
                        //执行删除
                        if (mId != '') {
                            mId = mId.substring(1);
                        }
                        if (rId != '') {
                            rId = rId.substring(1);
                        }
                        self._delNodeModule(mId, rId, function (data) {
                            if (data.result == 'ok') {
                                self.showMsg(title[2]);
                                //更新前端列表
                                $.each(allsel, function (i, id) {
                                    delete nodes[id];
                                });
                                initPopHtml($this);
                            } else {
                                self.showMsg(data.msg);
                            }
                        });

                        return false;
                    },
                    '550px', title[4],
                    function ($this) {
                        //初始化树
                        initPopHtml($this.$content);
                    },
                    null, null, title[5]);

            });
        },
        //鑷姩鍒涘缓娴佺▼鏂瑰潡
        _autoMakeFlowMap: function (data) {
            var self = this;
            var colNum = 7;
            var row = 0, col = 0;
            var rdy = '';//璁板綍宸茬粡瀛樺湪鐨勬祦绋�
            var max = self.curDrawLayer.nodeMax - 1;
            if (max > 1) {
                row = parseInt(max / colNum);
                col = max % colNum;
            }

            $.each(data, function (i, obj) {
                //鍒ゆ柇瀵煎叆鐨勬祦绋嬫槸鍚﹀凡缁忓紩鍏ヨ繃
                var element = self.curDrawLayer._nodes[obj.id];
                if (element) {
                    rdy += obj.name + '(' + obj.id + ')<br>';
                    return self.CONTINUE;
                }
                if (col >= colNum) {
                    row++;
                    col = 0;
                }
                self._createMapNode({
                    id: obj.id,
                    name: obj.name,
                    x: (col++) * 200 + 20,        //搴旇浠庨厤缃俊鎭腑鑾峰彇鎬诲搴�
                    y: row * 160 + 70      //搴旇浠庨厤缃俊鎭腑鑾峰彇鎬婚珮搴�
                });
            });
            if (rdy != '') {
                self.showMsg(rdy, self.getLang('static.rdyImport'));
            }

        },
        //打开流程旋转框
        _openFromServer: function () {
            var self = this;
            this.openWinForSelFlow(function (flowid, flowname) {
                self.reloadFlowById(flowid);
            });
        },
        //供外部调用,在不刷新页面的情况下加载其他流程定义
        reloadFlowById: function (flowid, ver) {
            this.zrender.clear();
            this.dataid = flowid;
            this.flowid = undefined;
            this.id = undefined;
            this.data = undefined;
            //如果需要打开某个版本可以在_loadData中传入版本参数
            this._loadData(ver);
        },
        //复制流程
        _copydata: function () {
            var self = this;
            if (self.showtype == 5 || self.drawLayers.length > 1) {
                $.confirm({
                    title: this.getLang('static.info'),
                    content: this.getLang(self.showtype == 5 ? 'static.nocopy' : 'static.opensub'),
                    type: 'blue',
                    icon: 'glyphicon glyphicon-info-sign',
                    backgroundDismiss: true, //是否允许点击背景关闭
                    buttons: {
                        ok: {
                            text: this.getLang('static.ok'),
                            btnClass: 'btn-primary'
                        }
                    }
                });
                return;
            }
            $.confirm({
                title: this.getLang('static.info'),
                content: this.getLang('static.copyInput') + '<br/><input type="text" class="form-control input-sm" value="copy_' + this.flowid + '" name="tmpText">',
                type: 'blue',
                icon: 'glyphicon glyphicon-info-sign',
                // backgroundDismiss: true, //是否允许点击背景关闭
                buttons: {
                    ok: {
                        text: this.getLang('static.ok'),
                        btnClass: 'btn-primary',
                        action: function () {
                            var newFlowid = $('input[name="tmpText"]').val();
                            if (!newFlowid || newFlowid == '') {
                                self.showMsg(self.getLang('prop.flowidnull'));
                                return false;
                            }
                            if (!self.isSaveFlow) {
                                self.showMsg(newFlowid + self.getLang('prop.flowexist'));
                                return false;
                            }
                            var oldFlowid = self.flowid;
                            self.dataid = newFlowid;
                            self.flowid = newFlowid;
                            self.curDrawLayer.flowid = newFlowid;

                            self.data.flowInfo.flowId = newFlowid;
                            self.data.mapData.flowId = newFlowid;

                            var showFlowid = newFlowid + ' ( Ver: 1 )';
                            self.statusFlowid.html(showFlowid);
                            self.statusFlowid.attr('title', showFlowid);
                            delete self.drawLayers[oldFlowid];
                            self.drawLayers[newFlowid] = self.curDrawLayer;
                            //规则需要拷贝复制
                            $.each(self.data.process, function (key, node) {
                                self.copyNodeRule(node, self.curDrawLayer, true);
                            });
                            ;
                            self._showProperties();
                        }
                    },
                    cancel: {
                        text: this.getLang('static.cancel'),
                        btnClass: 'btn-primary'
                    }
                },

                onOpen: function () {
                    self.checkAndChange($('input[name="tmpText"]'),
                        'checkInputCharNumber', 32, function (value) {
                            self.checkFlowIdIsExistFromServer(value);
                        });
                }
            });
        },
        //响应清空处理
        _ckClearCanvas: function () {
            var self = this;
            this.applyQuestion(this.getLang('static.clear'), function () {
                self._initCanvas();
                self._initTmpData();
            });
        },
        //响应对齐处理
        _alignNode: function () {
            var self = this;
            var show = (self.selAreaNodes.length < 2);
            var aligninfo = show ? this.getLang('static.aligninfo') :
                ("<input type='radio' name='alignType' value='1'>" + this.getLang('static.alignleft')
                    + "<br><input type='radio' name='alignType' value='2'>" + this.getLang('static.alignright')
                    + "<br><input type='radio' name='alignType' value='3'>" + this.getLang('static.alignup')
                    + "<br><input type='radio' name='alignType' value='4'>" + this.getLang('static.aligndown')
                );
            $.confirm({
                title: this.getLang('static.align'),
                content: aligninfo,
                type: 'blue',
                icon: show ? 'glyphicon glyphicon-info-sign' : 'glyphicon glyphicon-question-sign',
                buttons: {
                    ok: {
                        text: this.getLang('static.ok'),
                        btnClass: 'btn-primary',
                        action: function () {
                            var type = $('input[name="alignType"]:checked').val();
                            if (type == '1') {
                                self._chgAlignNode(true, true);
                            } else if (type == '2') {
                                self._chgAlignNode(true, false);
                            } else if (type == '3') {
                                self._chgAlignNode(false, true);
                            } else if (type == '4') {
                                self._chgAlignNode(false, false);
                            }
                        }
                    },
                    cancel: {
                        text: this.getLang('static.cancel'),
                        btnClass: 'btn-primary'
                    }
                }
            });
        },
        //响应泳道处理
        _swimlanes: function () {
            var self = this;
            if (!$.isEmptyObject(this.curDrawLayer._swimlane)) {
                this._makelane();
                return;
            }
            var swimlanesinfo = this.getLang('static.swimlanesdirector') +
                "<input type='radio' name='lanetype' value='1' checked>" + this.getLang('static.swimlanesv')
                + "<input type='radio' name='lanetype' value='2'>" + this.getLang('static.swimlanesh')
                + "<br/>" + this.getLang('static.swimlanesnum') + "<input type='text' name='lanenum' value='2'>";

            $.confirm({
                title: this.getLang('static.swimlanes'),
                content: swimlanesinfo,
                type: 'blue',
                icon: 'glyphicon glyphicon-info-sign',
                buttons: {
                    ok: {
                        text: this.getLang('static.ok'),
                        btnClass: 'btn-primary',
                        action: function () {
                            self._makelane($('input[name="lanetype"]:checked').val(),
                                $('input[name="lanenum"]').val());
                        }
                    },
                    cancel: {
                        text: this.getLang('static.cancel'),
                        btnClass: 'btn-primary'
                    }
                }
            });
        },

        //响应打开
        _openLocalFile: function () {
            $("#files").click();
        },
        //===========响应事件的辅助处理=========================
        //读取选中的文件内容
        _fileImport: function (target) {
            var self = this;
            //获取读取我文件的File对象
            var selectedFile = target.files[0]; //document.getElementById('files')
            // var name = selectedFile.name;//读取选中文件的文件名
            // var size = selectedFile.size;//读取选中文件的大小
            // console.log("文件名:"+name+"大小:"+size);

            var reader = new FileReader();//这是核心,读取操作就是由它完成.
            reader.readAsText(selectedFile);//读取文件的内容,也可以读取文件的URL
            reader.onload = function () {
                try {
                    //当读取完成后回调这个函数,然后此时文件的内容存储到了result中,直接操作即可
                    self.data = JSON.parse(this.result);
                    if (!self.data.mapData) {
                        throw new Error();
                    }
                    self.id = undefined;
                    self.dataid = undefined;
                    self.flowid = undefined;
                    self._loadData();
                } catch (e) {
                    self.showMsg(self.getLang('msg.formatError.notJson'));
                }
            }
        },
        //保存到本地
        _saveToLocal: function () {
            var name = this.curDrawLayer.flowid + ".json",
                data = JSON.stringify(this.curDrawLayer.data);
            var export_blob = new Blob([data], {type: "text/plain;charset=UTF-8"});

            var userAgent = navigator.userAgent;

            if (this.showtype == 5) {
                name = this.dataid + ".json";
            }
            // Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0

            // Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
            // Chrome/76.0.3809.132 Safari/537.36

            // Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; Touch; .NET4.0C; .NET4.0E;
            // .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; Tablet PC 2.0; rv:11.0)
            // like Gecko

            //判断是否是IE11
            if (userAgent.indexOf("Trident") != -1) {
                window.navigator.msSaveBlob(export_blob, name);
            } else {
                var urlObject = window.URL || window.webkitURL || window;
                var save_link = document.createElementNS("http://www.w3.org/1999/xhtml", "a");
                save_link.href = urlObject.createObjectURL(export_blob);
                save_link.download = name;
                this._fake_click(save_link);
            }
        },
        _saveImageToLocal: function (name, data) {
            var userAgent = navigator.userAgent;
            // console.log(userAgent);
            //判断是否是IE11
            if (userAgent.indexOf('Trident') != -1 || userAgent.indexOf('Edge') != -1) {
                var arr = data.split(',');
                var mime = arr[0].match(/:(.*?);/)[1];
                var bstr = atob(arr[1]);
                var n = bstr.length;
                var u8arr = new Uint8Array(n);
                while (n--) {
                    u8arr[n] = bstr.charCodeAt(n);
                }
                window.navigator.msSaveBlob(new Blob([u8arr], {type: mime}), name);
            } else {
                //webkit
                var save_link = document.createElementNS("http://www.w3.org/1999/xhtml", 'a');
                save_link.href = data;
                save_link.download = name;
                this._fake_click(save_link);
            }
        },

        //保存到服务器
        _saveToServer: function (savenew) {
            // 需要根据showtype=1/5来区分是实例数据还是流程定义数据
            var self = this;
            var nodes = this.curDrawLayer.data.mapData.nodes;
            var nodeIds = Object.keys(nodes);
            var existStart = false;
            var existEnd = false;
            for (var i = 0; i < nodeIds.length; i++) {
                if (nodeIds[i] == ('Start')) {
                    existStart = true;
                } else if (nodeIds[i].indexOf('End') >= 0) {
                    existEnd = true;
                }
            }
            if (!existStart || !existEnd) {
                self.showMsg(self.getLang('static.notExistStartAndEnd'));
                return;
            }
            var url = this.options.serverUrl + "savedata" + this.options.suffix;
            var para = "showtype=" + this.showtype + "&flowId=" + this.flowid;
            if (this.showtype == 1) {
                //判断flowid是否为默认值
                if (self.curDrawLayer.flowid == 'NewFlowId') {
                    self.showMsg(self.getLang('static.savemsg'));//('请先打开流程属性编辑界面并修改默认的流程ID');
                    return;
                }
                para += "&saveFlag=" + (savenew);  //1=版本自动 2=保存新版本 3=版本不变
            } else if (this.showtype == 5) {
                para += "&workid=" + this.data.workId;
            }
            if ($.isEmptyObject(this.curDrawLayer._nodes)) {
                self.showMsg(self.getLang('static.nodesnull'));
                return;
            }
            var alone = this._checkNodeForSave();
            if (alone != '') {
                self.showMsg(self.getLang('static.nodealone') + '<BR>' + alone);
                return;
            }

            para += "&data=" + encodeURIComponent(JSON.stringify(this.curDrawLayer.data));
            //规则数据一起发送后台保存
            var tmpRule = [];
            $.each(this.curDrawLayer.rules || [], function (key, item) {
                if (!item) {
                    return self.CONTINUE;
                }
                tmpRule.push(item);
            });
            para += "&rule=" + encodeURIComponent(JSON.stringify(tmpRule));

            var msg = self.getLang('static.loaderror') + '<br>' + url + "?" + para;
            this._ajaxToServer(url, para, function (data) {
                //           数据获取返回            参数失败时         会话过期时
                var result = data['result'] || data['restype'] || data['status'];
                if (result == 'err' || result == 'error') {
                    self.showMsg(data['msg'] || self.getLang('static.saveError'));
                    return;
                }
                if (self.showtype == 1) {
                    var flowInfo = self.curDrawLayer.data['flowInfo'];
                    flowInfo['id'] = data['id'];
                    //20200923 LIYS 如果版本发生变化时,需要重新加载数据(因为规则数据的id可能发生变化)
                    var oldVer = flowInfo['version'];
                    flowInfo['version'] = data['version'];
                    var newVer = flowInfo['version'];
                    if (oldVer != newVer && tmpRule.length > 0) {
                        self.showMsg(self.getLang('static.saveok'), null, null, 0);
                        self.reloadFlowById(self.flowid);
                        return;
                    }

                    if (self.curDrawLayer.isMain) {
                        //主流程保存的时候应该更新下id
                        self.id = data['id'];
                    }
                }
                //修改版本信息显示
                var showFlowid = self.curDrawLayer.flowid + ' ( Ver: ' + data['version'] + ' )';
                self.statusFlowid.html(showFlowid);
                self.statusFlowid.attr('title', showFlowid);
                //如果保存的是主流程则需要更新
                if (self.flowid == self.curDrawLayer.flowid) {
                    self.maxVer = data['version'];//保存后的版本也是最后版本,更新
                }
                self.curDrawLayer.rules = {};//清空
                //20201102 LIYS 增加保存后的回调方法
                try {
                    afterSave(self.isNew, self.showtype);
                } catch (e) {
                }
                ;
                self.showMsg(self.getLang('static.saveok'), null, null, 0);

            }, msg, true);
        },
        _checkNodeForSave: function () {
            var alone = '';
            $.each(this.curDrawLayer._nodes, function (i, node) {
                if (node.routes == null || $.isEmptyObject(node.routes)) {
                    alone += node.name + '(' + node.id + '),';
                }
            });
            return alone;
        },

        //模拟点击
        _fake_click: function (obj) {
            var ev = document.createEvent("MouseEvents");
            ev.initMouseEvent(
                "click", true, false, window, 0, 0, 0, 0, 0
                , false, false, false, false, 0, null
            );
            obj.dispatchEvent(ev);
        },
        //创建泳道
        _makelane: function () {
            var self = this;
            var lanetype, lanenum;
            if (arguments.length > 0) {
                lanetype = parseInt(arguments[0]);
                lanenum = parseInt(arguments[1]);
                var name = self.curDrawLayer.data ? self.curDrawLayer.data.flowInfo.flowName : '未命名';
                self.curDrawLayer._swimlane = new SwimLane({
                    __Flowdesigner: self,
                    __drawLayer: self.curDrawLayer,

                    id: 'swimlane',
                    name: name,
                    lanenum: lanenum,
                    lanetype: lanetype,
                    lanewidth: [],       //如果不清空的话,会有上次创建对象中的数据,不知道为啥????
                    lanename: []
                });
                self.curDrawLayer._swimlane.addSelfToZr();
            } else {
                self.curDrawLayer._swimlane.addOneLane();
            }
        },
        //按照不同的方式进行对齐处理
        _chgAlignNode: function (isH, isMin) {
            var self = this;
            var pos = isH ? this.selAreaNodes[0].x : this.selAreaNodes[0].y;
            $.each(this.selAreaNodes || [], function (i, node) {
                if (!node) {
                    return self.CONTINUE;
                }
                pos = isMin ? Math.min(isH ? node.x : node.y, pos) : Math.max(isH ? node.x : node.y, pos);
            });

            $.each(this.selAreaNodes || [], function (i, node) {
                if (!node) {
                    return self.CONTINUE;
                }
                node.alignNode(isH, pos);
            });
        },
        //流程监控时显示额外节点信息
        _showAloneNodes: function () {

        },

        //==============数据加载解析===========================
        //从数据中恢复节点和路由
        _openFlowVer: function () {
            var self = this;
            var ver = self.maxVer;
            if (ver < 2) {
                self.showMsg(self.getLang('static.onlyver'));
                return;
            }
            var html = '<select name="popSel" style="width:270px">';
            for (var i = ver; i > 0; i--) {
                html += '<option value="' + i + '">' + self.getLang('static.showver') + i + '</option>';
            }
            html += '</select>';
            self.popSelWin(self.getLang('static.selver'), html, function ($this) {
                var selVer = $this.find('select[name="popSel"]').val();
                if (selVer) {
                    self.data = null;
                    self._loadData(parseInt(selVer));
                } else {
                    self.showMsg(self.getLang('static.selver'));
                    return false;
                }
            }, '300px');
        },
        isNew: false,
        _loadData: function (version, callback) {
            var self = this;
            if (self.showtype >= 8) {
                if (callback) callback(self);
                //泳道需要的数据初始化
                this._initDrawLayer();
                return;
            }
            if (this.data) {
                if (callback) callback(self);
                var showtype = self.showtype;
                if (showtype == 5) {
                    //实例修改时,验证数据必须有workid
                    if (!this.data.workId || (this.dataid && this.data.workId != this.dataid)) {
                        $.confirm({
                            title: this.getLang('static.info'),
                            content: this.getLang('static.dataerror'),
                            type: 'blue',
                            icon: 'glyphicon glyphicon-info-sign',
                            // backgroundDismiss: false, //是否允许点击背景关闭
                            buttons: {
                                ok: {
                                    text: this.getLang('static.ok'),
                                    btnClass: 'btn-primary',
                                    action: function () {
                                        //self._creatNewFlow();
                                    }
                                }
                            }
                        });
                        return;
                    }
                    this.dataid = this.data.workId;
                }

                if (this.data.workId && this.showtype == 1) {
                    //如果数据中包含workId,则强制showtype=5
                    this.showtype = 5;
                }
                this._showFlowFromData();
            } else {
                this._loadFromServer(this.dataid, function (data) {
                    self.localeVal = data.localeVal ? data.localeVal : getLang();
                    delete data.localeVal;
                    self.data = data;
                    if (callback) callback(self);
                    if (!(self.dataid == null
                        || self.dataid == undefined
                        || self.dataid == 'NewFlowId'
                        || self.dataid.trim() == '')) {
                        self.isNew = false;
                        //从服务器端加载数据
                        if (data.status && data.code) {
                            self.showMsg(self.getLang('static.loaderror'), null, function () {
                                self._creatNewFlow();
                            });
                            return;
                        }
                        if (self.showtype == 1 && !version) {
                            //不传入版本信息时,获取的是最后的版本
                            self.maxVer = data.flowInfo['version'];
                        }
                        self._loadData();
                    } else {
                        self._creatNewFlow();
                    }
                }, version);
            }
        },
        //根据data数据显示
        _showFlowFromData: function () {
            var self = this;
            var watermark = this.data.orgName;
            if (watermark) {
                delete this.data['orgName'];
                this._showFlowFromDataInit(watermark);
                if (this.showtype == 1 || this.showtype == 5) {
                    //如果是从后端获取到到数据,此时需要对表单进行信息获取
                    if (this.data['flowInfo']) {
                        var forms = this.data.flowInfo['forms'];
                        var formIds = '', formNames = {};
                        $.each(forms || [], function (key, form) {
                            if (!form) {
                                return self.CONTINUE;
                            }
                            if (key == 'FlowTrack') {
                                return self.CONTINUE;
                            }
                            formIds += ';' + key;
                            formNames[key] = form.name;
                        });
                        if (formIds != '') {
                            self.getFormInfoFromServer(formIds.substring(1), formNames);
                        }
                    }
                    //人员信息获取放到打开属性框时去加载
                }
            } else {
                //从服务器上获取水印文字
                this._loadWatermarkAndDo(function (watermark) {
                    self._showFlowFromDataInit(watermark);
                    if (self.showtype == 1 || self.showtype == 5) {
                        //如果是从后端获取到到数据,此时需要对表单进行信息获取
                        if (self.data['flowInfo']) {
                            var forms = self.data.flowInfo['forms'];
                            var formIds = '', formNames = {};
                            $.each(forms || [], function (key, form) {
                                if (!form) {
                                    return self.CONTINUE;
                                }
                                if (key == 'FlowTrack') {
                                    return self.CONTINUE;
                                }
                                formIds += ';' + key;
                                formNames[key] = form.name;
                            });
                            if (formIds != '') {
                                self.getFormInfoFromServer(formIds.substring(1), formNames);
                            }
                        }
                        //人员信息获取放到打开属性框时去加载
                    }
                });
            }
        },
        //根据data显示,并添加水印
        _showFlowFromDataInit: function (watermark) {
            var self = this;
            var showtype = this.showtype;
            this.flowid = 'NewFlowId';
            if (this.data.mapData) {
                this.flowid = this.data.mapData.flowId;
            } else {
                self.showMsg(self.getLang('static.loaderror'));
            }

            this.zrender.clear();
            var waterTxt = null;
            if (showtype == 1 || showtype == 5) {
                this._initWatermark(this.zrender, watermark);//水印不动
                this._initDrawLayer();
                this._chgStatusTitle(this.data['flowInfo']);
            } else {
                this._initDrawLayer();
                waterTxt = this._initWatermark(this.curDrawLayer.zrGroup, watermark);//水印跟随拖动
            }
            this._initTmpData();
            if (!this.data.mapData) {
                return;
            }
            this._parseData(this.curDrawLayer, this.data);
            //调整水印位置,根据节点位置使水印能在有节点的位置中间
            if (waterTxt) {
                self.curDrawLayer.checkAllPoint();
                var point = self.curDrawLayer.rectPoint;
                var txt = waterTxt.style.text;
                var w = point['maxX'] + 50, h = point['maxY'] + 50;
                var fontSize = w / txt.length;
                waterTxt.attr({
                    origin: [w / 2, h / 2],
                    style: {
                        x: w / 2,
                        y: h / 2 + (fontSize / 2 - 10),
                        font: fontSize + 'px Microsoft Yahei'
                    }
                });
            }
            self.curDrawLayer.isMain = true;
            switch (this.showtype) {
                case 1:
                    if (this.flowid == 'NewFlowId') {
                        self._showProperties();
                    } else {
                        self._hidePopWin();
                    }
                    break;
                case 4:
                    //自动测试开始
                    self._autoTest();
                    break;
                case 6:
                    //生成两条垂直线，用来显示当前鼠标位置
                    self._makeTwoLine();
                    break;
            }
            ;
        },
        //更新状态栏中的标题
        _chgStatusTitle: function (data) {
            if (data) {
                this.statusFlowname.html(data['flowName']);
                this.statusFlowname.attr('title', data['flowName']);
                var showFlowid = data['flowId'] + ' ( Ver: ' + data['version'] + ' )';
                this.statusFlowid.html(showFlowid);
                this.statusFlowid.attr('title', showFlowid);

                var ff = this.getLang('static.nogroup');//'未分类';
                var flowtype = data['flowType'];
                if (flowtype && flowtype['name']) {
                    ff = flowtype['name'];
                    if (flowtype['id']) {
                        ff += '(' + flowtype['id'] + ')';
                    }
                }
                this.statusType.html(ff);
                this.statusType.attr('title', ff);
            }
        },
        //获取水印
        _loadWatermarkAndDo: function (callback) {
            var self = this;
            //新建时从服务器上获取水印文字
            this._loadFromServer(null, function (data) {
                var watermark = data.orgName;
                callback(watermark);
            });
        },
        //创建一个新的数据对象
        _creatNewFlow: function () {
            var self = this;
            this.zrender.clear();
            this.dataid = 'NewFlowId';
            this.flowid = 'NewFlowId';
            this.id = undefined;

            this.data = FlowInit.initFlow(this);
            this.isNew = true;
            this._loadData();
        },
        //加载子流程数据
        loadSubData: function (subflowid, subnode) {
            var self = this;
            var subLayer = self.drawLayers[subflowid];
            if (subLayer) {
                if (this.showtype == 3) {
                    var flag = this.options.loadSubFlag || 0;
                    // 1. 只获取实例数,
                    if (flag == 1) {
                        var getDataForMonitor = function (flowId) {
                            var url = self.options.serverUrl + "getDataForMonitor" + self.options.suffix;
                            var para = 'flowid=' + flowId;
                            var msg = self.getLang('static.loaderror') + '<br>' + url + "?" + para;

                            if (dev) {
                                url = "/tmpdata/getDataForMonitor.json";
                            }

                            self._ajaxToServer(url, para, function (data) {
                                //处理返回结果
                                self._showSubFlow(data, subLayer, subnode);
                            }, msg);
                        };

                        getDataForMonitor(subflowid);
                        return;
                    }
                    // 2. 重新获取所有数据
                    else if (flag == 2) {
                        self._loadFromServer(subflowid, function (data) {
                            self._showSubFlow(data, null, subnode);
                        });
                        return;
                    }
                    // 0. 只加载一次
                }
                self._showSubFlow(null, subLayer, subnode);
            } else {
                self._loadFromServer(subflowid, function (data) {
                    self._showSubFlow(data, null, subnode);
                });
            }
        },
        //从服务器上获取数据
        _loadFromServer: function (dataid, callback, version) {
            var self = this;
            var url = this.options.serverUrl + "chartdata" + this.options.suffix;
            var para = null;
            if (dataid) {
                para = 'dataid=' + dataid;
                if (version) {
                    para += ':' + version;
                }
                para += "&showtype=" + this.showtype;
                if (this.showtype == 2) {
                    //获取流程跟踪,在没有登陆的情况下,需要传入identifier
                    if (this.identifier) {
                        para += "&identifier=" + this.identifier;
                    }
                    if (this.tenantid) {
                        para += "&tenantid=" + this.tenantid;
                    }
                }
            } else {
                para = 'showtype=0';//固定值0,用于获取orgName
            }
            if (dev) {
                if (dataid) {
                    url = "/tmpdata/" + dataid + "_" + this.showtype + ".json";
                } else {
                    url = "/tmpdata/orgName.json";
                }
            }
            //---------------------
            var msg = '数据加载失败!<br>' + url + "?" + para;
            this._ajaxToServer(url, para, callback, msg);
        },
        //实际执行交互
        _ajaxToServer: function (url, para, callback, errmsg, post, async) {
            var self = this;
            $.ajax({
                type: post ? 'POST' : 'GET',
                dataType: 'json',
                url: url,
                data: para,
                async: ((typeof async == 'undefined') ? true : async),
                cache: false,
                success: function (result) {
                    var data = result;//.data;
                    callback(data);
                },
                error: function () {
                    if (!errmsg) {
                        errmsg = self.getLang('static.loaderror') + '<br>' + url + "?" + para;
                    }
                    self.showMsg(errmsg);
                }
            });
        },
        //解析数据,并在添加到画布上
        _parseData: function (drawLayer, data) {
            var self = this;
            //添加层到画布中
            this.zrender.add(drawLayer.zrGroup);
            //设置层数据对象
            drawLayer.data = (data);
            drawLayer.nodeMax = data.mapData.nodeNum;
            drawLayer.routeMax = data.mapData.routeNum;
            var allObj = this._chgNodes(data);
            $.each(data.mapData.nodes || [], function (i, node) {
                if (!node) {
                    return self.CONTINUE;
                }
                self.loadNode(allObj[node.id], node, drawLayer);
                delete allObj[node.id];
                drawLayer.checkNodePoint(node.x, node.y);
            });

            $.each(data.mapData.lines || [], function (i, line) {
                if (!line) {
                    return self.CONTINUE;
                }
                var route = self._loadLine(allObj[line.id], line, drawLayer);
                delete allObj[line.id];
                if (route.dragPoints.length == 3) {
                    drawLayer.checkLinePoint(route.dragPoints[2].x, route.dragPoints[2].y);
                }
            });
            if (data.mapData.swimlane) {
                self._loadSwimlane(data.mapData.swimlane, drawLayer);
                drawLayer.checkSwimPoint();
            }

            //在监控时,会有节点已经不在流程图上的情况出现(删除/自由提交)
            switch (this.showtype) {
                case 2:
                    //流程跟踪图显示时,需要在画布上增加图标示例,动画显示
                    this._initIconForTracklog();
                    break;
                case 3:
                    this._makeAloneNode(allObj, drawLayer);
                    break;
                case 1:
                case 5:
                    data.flowInfo.forms = this.sortObject(data.flowInfo.forms, 'id', 'sort');
                    this._makeRuleFromXml(drawLayer, data);
                //不要break，因为下面的maxPoint需要赋值
                default:
                    drawLayer.maxPoint = [drawLayer.rectPoint['maxX'], drawLayer.rectPoint['maxY']];
            }
            //数据加载完成后,执行一个回调方法,告诉外部页面,当前页面加载完成(在页面被嵌入时很有必要)
            try {
                var w = drawLayer.maxPoint[0], h = drawLayer.maxPoint[1];
                if (this.showtype == 2 || this.showtype == 3) {
                    //如果时子流程加载时,需要跟主流程的大小对比
                    if (this.curDrawLayer.flowid != drawLayer.flowid) {
                        w = Math.max(this.curDrawLayer.maxPoint[0], w) + 10;
                        h = Math.max(this.curDrawLayer.maxPoint[1], h) + 10;
                    }
                    if (this.options['resizeWidth']) {
                        this.zrender.resize({
                            width: w
                        })
                    }
                    if (this.options['resizeHeight']) {
                        this.zrender.resize({
                            height: h
                        })
                    }
                }

                gThisPageLoadSuccess(data, [w, h]);
            } catch (e) {
            }
        },
        _makeAloneNode: function (aloneNodes, drawLayer) {
            var self = this;
            //drawLayer.aloneNodes = allObj;
            var len = Object.keys(aloneNodes).length;
            if (len > 0) {
                var startX = drawLayer.rectPoint['maxX'] + 30;
                var startY = drawLayer.rectPoint['minY'] + 5;
                var stroke = this.options.flownode.color.define;
                var w = 120, h = 80;

                var minPoint = drawLayer.getMinPoint([startX, startY], 25);
                startX = minPoint[0];
                startY = minPoint[1];

                var rect = new zRender.Rect({
                    z: drawLayer.getZLevel(this.zArr.node),
                    scale: [1, 1],  //缩放比例
                    origin: [0, 0], //设置缩放中心
                    position: [startX, startY],
                    style: {
                        lineWidth: 2,
                        fill: '#fff',
                        stroke: stroke,
                        lineDash: [4, 1],
                        strokeNoScale: true, //描边粗细不随缩放而改变，false 则会根据缩放同比例缩放描边粗细。
                        transformText: true, //文字是否跟随变换效果，仅对 Path 或 Image 元素有效
                        text: this.getLang('menu.alone'),
                        textPosition: 'top',
                        textAlign: 'center'
                    },
                    shape: {
                        x: 0,
                        y: 0,
                        r: 5,
                        width: w,
                        height: h * len + 10
                    },
                    draggable: false
                });  //矩形包围框
                drawLayer.zrGroup.add(rect);
                var k = 0;
                $.each(aloneNodes, function (key, node) {
                    var map = {
                        id: node.nodeid,
                        name: node.nodename,
                        nodeType: 10,
                        x: startX + 33,
                        y: startY + 15 + h * (k++)
                    };
                    self.loadNode(node, map, drawLayer);
                })

                // 修正最大值和最小值,用于返回
                //当前页面对象的最大坐标值
                drawLayer.rectPoint['maxX'] = startX + 120 + 10;
                drawLayer.rectPoint['maxY'] = Math.max(startY + h * len + 10, drawLayer.rectPoint['maxY']);
            }

            drawLayer.maxPoint = [drawLayer.rectPoint['maxX'], drawLayer.rectPoint['maxY']];
        },
        _makeRuleFromXml: function (drawLayer, data) {
            var ruleHtml = data['RuleHtml'];
            var self = this;
            if (ruleHtml && Object.keys(ruleHtml).length > 0) {
                $.each(ruleHtml, function (id, html) {
                    if (html) {
                        var tmpRule = {
                            id: id,
                            oldId: id,
                            flowid: self.flowid,//流程id总是有的
                            workid: self.showtype == 5 ? self.dataid : '',//实例编辑时
                            html: html
                        };
                        drawLayer.rules[id] = tmpRule;
                    }
                });
            }
            delete data['RuleHtml'];
        },
        //从数据中获取到所有节点和路由数据
        _chgNodes: function (data) {
            var self = this;
            var result = {};
            switch (this.showtype) {
                case 1:
                case 5:
                    var nodes = data.process;
                    $.each(nodes || [], function (i, node) {
                        if (!node) {
                            return self.CONTINUE;
                        }
                        result[node.id] = node;
                        //获取路由
                        $.each(node.transitions || [], function (j, route) {
                            if (route) {
                                result[route.id] = route;
                            }
                        });
                    });
                    break;
                // case 4://自动测试时,也需要修改图标演示
                case 2:
                case 6:
                    //流程跟踪图,办理情况
                    this._convertDataForTrackLog(data, result);
                    break;
                case 3:
                    this._convertDataForMonitor(data, result);
                    break;
            }
            return result;
        },
        //解析数据,流程监控部分数据
        _convertDataForMonitor: function (data, result) {
            var instanceNums = data.instanceNums;   //数组
            if (instanceNums) {
                $.each(instanceNums || [], function (key, nodeNum) {
                    if (typeof (nodeNum) == 'object') {
                        result[nodeNum.nodeid] = nodeNum;
                    }
                });
            }
        },
        //解析数据,流程跟踪部分数据
        _convertDataForTrackLog: function (data, result) {
            //流程跟踪图的数据格式新格式如下,如果不是则需要先行转换
            var runData = data.runData; //data.Map,现行xml返回值
            if (!runData) {
                return;
            }
            //跳过节点
            var jumpNodes = runData['JumpNodes'] || [];
            if (typeof jumpNodes === 'string') {
                jumpNodes = jumpNodes.split(';');
            }
            this._makeDataForTrack(result, jumpNodes, 'jumpurl');
            //已办理节点
            var doneNodes = runData['DoneNodes'] || [];
            if (typeof doneNodes === 'string') {
                doneNodes = doneNodes.split(';');
            }
            this._makeDataForTrack(result, doneNodes, 'doneurl');
            //当前活动节点
            var nowNodes = runData['NowNodes'] || [];
            if (typeof nowNodes === 'string') {
                nowNodes = nowNodes.split(';');
            }
            this._makeDataForTrack(result, nowNodes, 'nowurl');
            //超期节点
            var extendedNodes = runData['ExtendedNodes'] || [];
            if (typeof extendedNodes === 'string') {
                extendedNodes = extendedNodes.split(';');
            }
            this._makeDataForTrack(result, extendedNodes, 'waringurl');


            if (this.nodeid && result[this.nodeid]) {
                result[this.nodeid]['isCur'] = true;
            } else {
                $.each(nowNodes || [], function (i, node) {
                    if (node) {
                        result[node]['isCur'] = true;
                    }
                })
            }
            var historys = data.historys;
            if (historys) {
                var openUrl = this.options['testFlowPage'];
                var _chgLogSubfow = function (history, openUrl) {
                    if (history['action'].toLowerCase() === 'subflow') {
                        var memo = history['memo'],
                            subflows = memo.match(/\[[^\]]+\]/g);
                        for (var k = 0, iLen = subflows.length; k < iLen; k += 2) {
                            var _flowName = subflows[k].replace(/\[/g, '').replace(/\]/g, ''),
                                _workId = subflows[k + 1].replace(/\[/g, '').replace(/\]/g, '');
                            var _url = openUrl + '?workId=' + _workId;
                            var flowNameLink = ['<a tabindex="-1" target="_blank" href="', _url, '">', _flowName, '</a>'].join('');
                            var index = memo.indexOf(subflows[k]);
                            memo = memo.substring(0, index + 1) + flowNameLink + memo.substring(index - 1 + subflows[k].length);
                        }
                        memo = historyReplace(memo);//.replace(/实例ID\[[^\]]+\]/g, '');
                        history['memo'] = memo;
                    }
                };
                $.each(historys || [], function (i, history) {
                    var nodeid = history && history['nodeid'];
                    if (nodeid) {
                        //转换子流程的历史记录
                        _chgLogSubfow(history, openUrl);
                        if (result[nodeid]) {
                            var his = result[nodeid]['history'] || [];
                            his.push(history);
                            result[nodeid]['history'] = his;
                        }
                    }
                });
            }

        },

        //流程跟踪部分数据创建
        _makeDataForTrack: function (result, Nodes, type) {
            $.each(Nodes || [], function (i, Node) {
                if (Node) {
                    result[Node] = {
                        showtype: type,
                        isCur: false
                    };
                }
            });
        },

        //从数据中恢复节点对象
        loadNode: function (data, map, drawLayer) {
            var self = this;
            var node = self._makeFlowNode({
                __drawLayer: drawLayer,
                id: map.id,
                name: map.name,
                sortNum: self._getSortNum(map.id),
                nodetype: map.nodeType,
                x: map.x,
                y: map.y,
                //sub:map.sub,
                data: data,
                map: map
            });
            node.addSelfToZr(false);

            return node;
        },
        _getSortNum: function (id) {
            if (id == 'Start') {
                return 0;
            } else {
                var self = this;
                $.each(['Node', 'End', 'Gateway', 'Subflow', 'Event', 'Robot', 'Cluster', 'Virtual'],
                    function (i, key) {
                        id = id.replace(key, '');
                        if (parseInt(id) > 0) {
                            return self.BREAK;
                        }
                    });
                return parseInt(id);
            }
        },
        //从数据中恢复路由对象
        _loadLine: function (data, map, drawLayer) {
            var self = this;
            var tmpPoint = null;
            if (!$.isEmptyObject(map.point)) {
                tmpPoint = map.point;
            }
            var route = new Route({
                __Flowdesigner: self,
                __drawLayer: drawLayer,
                id: map.id,
                name: map.name,
                lineType: map.lineType, //路由类型,1直线,2折线
                dragTmpPoint: tmpPoint,
                fromNode: drawLayer._nodes[map.from],
                toNode: drawLayer._nodes[map.to],
                x1: map.x1,
                y1: map.y1,
                x2: map.x2,
                y2: map.y2,
                map: map,
                data: data
            });
            route.addSelfToZr(false);
            drawLayer.tmpRoutes[map.from + "_" + map.to] = route;


            return route;
        },
        //从数据中恢复泳道对象
        _loadSwimlane: function (lane, drawLayer) {
            var self = this;
            if (lane && lane.name) {
                var swimlane = new SwimLane({
                    __Flowdesigner: self,
                    __drawLayer: drawLayer,
                    id: 'swimlane',
                    name: lane.name,
                    lanetype: lane.laneType,
                    lanenum: lane.laneNum,
                    lanewidth: lane.laneWidth,
                    lanename: lane.laneName,
                    map: lane
                });
                swimlane.addSelfToZr(false);
            }
        },

        //监控时获取某一节点上的实例数据
        loadWorksByNodeid: function (flowid, nodeid, flag, callback) {
            var self = this;
            var url = self.options.serverUrl + "getWorksByNodeid" + self.options.suffix;
            var para = 'flowid=' + flowid + '&nodeid=' + nodeid;
            if (flag) {
                para += '&flag=' + flag;
            }
            var msg = self.getLang('static.loaderror') + '<br>' + url + "?" + para;

            if (dev) {
                url = "/tmpdata/getWorksByNodeid.json";
            }

            self._ajaxToServer(url, para, function (data) {
                callback(data);
            }, msg);
        },
        //===============自动测试部分==============================
        //开启自动测试,在数据加载后弹出对话框,确定后开始执行
        _testFlow: function (flag) {
            var url = '';
            var id = (this.curDrawLayer.data.flowInfo['id']);
            if (!id) {
                this.showMsg(this.getLang('static.nosave'));
                return;
            }
            if (this.curDrawLayer.data.flowInfo['active'] == 0) {
                this.showMsg(this.getLang('static.test'));
                return;
            }
            if (flag == 1) {
                url = this.options['testFlowPage'] + '?flowId=' + id;//this.curDrawLayer.flowid;
            } else {
                url = window.location.href;
                var pos = url.indexOf('?');
                if (pos != -1) {
                    url = url.substring(0, pos);
                }
                url += '?showtype=4&dataid=' + id;//this.curDrawLayer.flowid;
            }
            window.open(url);
        },
        _autoTest: function () {
            var self = this;
            var pageHtml = self.getLang('static.testflowid') +
                '<input type="text" class="form-control input-sm" value="' + this.id + '" name="flowid" disabled>'
                + self.getLang('static.testuserid') +
                '<input type="text" class="form-control input-sm" value="' + this.userid + '" name="userid"><br>';

            pageHtml += '<input type="checkbox" value="1" name="auto">' + self.getLang('static.testflowNextStep');
            +'租户ID:<input type="text" value="' + this.dataid + '" name="tenantid"><br>'
            + '数据源标示ID:<input type="text" value="' + this.dataid + '" name="identifier"><br>';
            $.confirm({
                backgroundDismiss: true,
                title: self.getLang('menu.autotest'),
                content: pageHtml,
                type: 'blue',
                icon: 'glyphicon glyphicon-info-sign',
                buttons: {
                    ok: {
                        text: this.getLang('static.ok'),
                        btnClass: 'btn-primary',
                        action: function () {
                            var url = self.options.serverUrl + 'start' + self.options.suffix;
                            var para = 'flowid=' + $('input[name="flowid"]').val()
                                + '&userid=' + $('input[name="userid"]').val();
                            var auto = $('input[name="auto"]:checked').val();
                            self.autoNxt = auto == '1';
                            var msg = self.getLang('static.testerror') + '<br>' + url + "?" + para;
                            self._ajaxToServer(url, para, function (data) {
                                self._actionBack(data);
                            }, msg);
                        }
                    },
                    cancel: {
                        text: this.getLang('static.cancel'),
                        btnClass: 'btn-primary'
                    }
                }
            });
        },
        //执行后的返回结果处理
        _actionBack: function (data) {
            var self = this;
            //1. 判断执行结果
            var result = data['result'];
            if (result == 'Success') {
                //1.1 成功后,根据结果刷新节点信息
                self._autoTestRefresh(data);
                //1.2 记录workid
                if (data['workid']) {
                    this.dataid = data['workid'];
                }
                //1.3 根据是否自动下一步
                if (this.autoNxt) {
                    setTimeout(self._autoTestToNxt(data), 500);
                }
            } else if (result == 'SelectNode') {
                this._selectNodeHtml(data);
            } else if (result == 'SelectAuthor') {
                this._selectNodeHtml(data);
            } else if (result == 'Claim') {
                //指定一个认领人
                var subjectionId = data['subjectionId'];
                var subjectionType = data['subjectionType'];
                var userid = '';
                // self.claim(userid);
            } else {
                //1.2 失败则退出
                $.confirm({
                    title: self.getLang('static.info'),
                    content: data['error'],
                    type: 'red',
                    icon: 'glyphicon glyphicon-info-sign',
                    backgroundDismiss: true, //是否允许点击背景关闭
                    buttons: {
                        ok: {
                            text: self.getLang('static.ok'),
                            btnClass: 'btn-primary',
                            action: function () {

                            }
                        }
                    }
                });
            }
        },
        _selectNodeHtml: function (data) {
            var self = this;
            var nxtNodes = data['nextNodes'];//数组
            /*{
                "doneNode": true,
                "groupName": "1",
                "keyId": "keyid",
                "nodeId": "nodeid",
                "nodeName": "nodename",
                "result": 1,
                "selectid": "selectid",
                "selectname": "selectname",
                "selected": true,
                "users": [
                    {
                        "authName": "authname",
                        "authType": "U",
                        "freeSelect": false,
                        "initAuthorValue": "initvalue",
                        "onlySelectUser": 1,
                        "selectAuthorName": "selectAuthname",
                        "selectAuthorValue": "selectAuth",
                        "selectType": 1
                    }
                ]
              }
             */
            // 自动测试选择节点
            var html = '<div>';
            $.each(nxtNodes || [], function (i, node) {
                if (!node) {
                    return self.CONTINUE;
                }
                var group = node.groupName;
                if (group) {
                    //单选时
                    html += '<label class="radio-inline ">' +
                        '<input type="radio" name="' + group + '" value="'
                        + node['selectid'] + '" ' + (node['selected'] ? 'checked' : '') + '>'
                        + node['selectname'] + '</label><br>';
                } else {
                    html += '<label class="checkbox-inline">' +
                        '<input type="checkbox" name="' + node['nodeId'] + '" value="'
                        + node['selectid'] + '" ' + (node['selected'] ? 'checked' : '') + '>'
                        + node['selectname'] + '</label><br>';
                }
                if (node['selected'] && node['users']) {
                    html += '<input type=text name="' + node['keyId'] + '-Author" class="selUser form-control input-sm" style="width:360px"><br>';
                }

            });
            html += '</div>';
            self.popSelWin(self.getLang('static.selnode'), html,
                function ($this) {
                    var groupObj = $this.find('input[type="radio"]:checked');
                    var groupSel = '';
                    $.each(groupObj, function (i, obj) {
                        groupSel += '&' + obj.value;
                    })
                    var checkObj = $this.find('input[type="checkbox"]:checked');
                    $.each(checkObj, function (i, obj) {
                        groupSel += '&' + obj.value;
                    })
                    if (groupSel != '') {
                        groupSel = groupSel.substring(1);
                    } else {
                        self.__Flowdesigner.showMsg(self.getLang('static.selnode'));
                        return false;
                    }
                    //人员信息获取,返回JSON格式
                    var selUser = $this.find('.selUser');
                    var users = {};
                    $.each(selUser || [], function (i, user) {
                        if (user) {
                            users[user.name] = user.value;
                        }
                    });
                    self._submitContinue(groupSel, JSON.stringify(users));

                },
                '400px', null,
                function ($this) {
                    //人员信息获取,返回JSON格式
                    var selUser = $this.$content.find('.selUser');
                    selUser.on('dblclick', function () {
                        var _this = $(this);
                        var org = {data: '', label: ''};
                        var win = $('.jconfirm-open');
                        win.hide();
                        selectUser(org, function (data) {
                            if (data) {
                                // var ids = data.data;
                                _this.val(data.data);
                                // _this.attr('data', data.data);
                                win.show();
                            }
                        });
                    });
                });
        },
        //刷新画布上的节点
        _autoTestRefresh: function (data) {
            var nodes = this.curDrawLayer._nodes;

            $.each(data['jumpNodes'] && data['jumpNodes'].split(';') || [], function (i, node) {
                if (node && node != '') {
                    nodes[node].chgNodeShapeForTest('jumpurl');
                    nodes[node].data = null;
                }
            });

            $.each(data['doneNodes'] && data['doneNodes'].split(';') || [], function (i, node) {
                if (node && node != '') {
                    nodes[node].chgNodeShapeForTest('doneurl');
                    nodes[node].data = null;
                    nodes[node].closeFlight();
                }
            });

            $.each(data['nowNodes'] && data['nowNodes'].split(';') || [], function (i, node) {
                if (node && node != '') {
                    nodes[node].chgNodeShapeForTest('nowurl');
                    nodes[node].data = 'ok';
                    nodes[node].drawNowFlight();
                }
            });

        },
        //自动执行提交下一节点
        _autoTestToNxt: function (data) {
            var nowNodes = data['nowNodes'].split(";");
            for (var i = 0; i < nowNodes.length; i++) {
                if ('' == nowNodes[i] || nowNodes[i].indexOf('End') > -1) {
                    continue;
                } else {
                    this.submitToNxt(nowNodes[0]);
                    break;
                }
            }
        },
        //执行提交到下一节点,自动提交/手动点击节点
        submitToNxt: function (nodeid) {
            if (!this.dataid) {
                //1.2 失败则退出
                $.confirm({
                    title: self.getLang('static.info'),
                    content: 'workid is null.',
                    type: 'red',
                    icon: 'glyphicon glyphicon-info-sign',
                    backgroundDismiss: true, //是否允许点击背景关闭
                    buttons: {
                        ok: {
                            text: self.getLang('static.ok'),
                            btnClass: 'btn-primary',
                            action: function () {

                            }
                        }
                    }
                });
                return;
            }
            var self = this;
            var url = self.options.serverUrl + 'submit' + self.options.suffix;
            var para = 'workid=' + this.dataid + "&nodeid=" + nodeid;
            var msg = self.getLang('static.testerror') + '<br>' + url + "?" + para;

            self._ajaxToServer(url, para, function (data) {
                self._actionBack(data);
            }, msg);
        },
        //交互后提交
        _submitContinue: function (selNodes, selAuthors) {
            if (!this.dataid) {
                //1.2 失败则退出
                $.confirm({
                    title: self.getLang('static.info'),
                    content: 'workid is null.',
                    type: 'red',
                    icon: 'glyphicon glyphicon-info-sign',
                    backgroundDismiss: true, //是否允许点击背景关闭
                    buttons: {
                        ok: {
                            text: self.getLang('static.ok'),
                            btnClass: 'btn-primary',
                            action: function () {

                            }
                        }
                    }
                });
                return;
            }
            var self = this;
            var url = self.options.serverUrl + 'submitContinue' + self.options.suffix;
            var para = 'workid=' + this.dataid + '&selectNodeids=' + encodeURIComponent(selNodes)
                + '&selectUserids=' + encodeURIComponent(selAuthors);
            var msg = self.getLang('static.testerror') + '<br>' + url + "?" + para;

            self._ajaxToServer(url, para, function (data) {
                self._actionBack(data);
            }, msg, true);
        },

        //认领操作执行
        _claim: function (userid) {
            var self = this;
            var url = self.options.serverUrl + 'claim' + self.options.suffix;
            var para = 'workid=' + this.dataid + "&userid=" + userid;
            var msg = self.getLang('static.testerror') + '<br>' + url + "?" + para;
            self._ajaxToServer(url, para, function (data) {
                self._actionBack(data);
            }, msg);
        },
        //重新自动测试
        _reAutoTest: function () {
            var self = this;
            var nodes = this.curDrawLayer._nodes;
            $.each(nodes || [], function (id, node) {
                if (!node) {
                    return self.CONTINUE;
                }
                node.chgNodeShapeForTest('defurl');
                node.data = null;
            });
            this.dataid = null;
            this._autoTest();
        },
        //==========获取配置的语言文字信息(全局调用)=====================
        getLang: function (key) {
            if (!key) return null;
            return this.getOptions('language.' + key);
        },
        getHtml: function (key) {
            return Template.get(key, this.getLang('html'));
        },
        getOptions: function (key) {
            if (!key) return null;
            var options = this.options;
            if (key.indexOf('.') != -1) {
                $.each(key.split('.') || [], function (i, _key) {
                    if (_key) {
                        options = options[_key];
                    }
                });
            } else {
                options = options[key];
            }
            return options;

            // return this.options[key];
        },
        //==============属性弹出页面==========================
        //应用按钮禁用/启用
        flowProperties: null,//流程属性框对象
        nodeProperties: null,//节点属性框对象
        lineProperties: null,//路由属性框对象
        _getFlowProperties: function () {
            if (this.flowProperties == null) {
                this.flowProperties = new FlowProperties(this.options, this);
            }
            return this.flowProperties;
        },
        getNodeProperties: function () {
            if (this.nodeProperties == null) {
                this.nodeProperties = new NodeProperties(this.options, this);
            }
            return this.nodeProperties;
        },
        getLineProperties: function () {
            if (this.lineProperties == null) {
                this.lineProperties = new LineProperties(this.options, this);
            }
            return this.lineProperties;
        },
        showPopWin: function (params) {
            var self = this;
            var popWin = $('#hzPopModal');
            var title = params['title'],
                popHtml = params['popHtml'],
                data = params['data'],
                initFun = params['initFun'],
                applyFun = params['applyFun'];
            //模态窗口显示之后,执行,用于初始化模态窗口要显示的内容
            popWin.off('show.bs.modal');
            popWin.on('show.bs.modal', function (event) {
                //使用jquery-ui的拖动功能
                $('.modal-dialog').draggable();
                $(this).css("overflow", "hidden");
                //console.log('模态窗口初始化.....')
                var modal = $(this);
                $('#hzPopModalLabel').html(title);

                //大小调整
                if (params['width']) {
                    modal.find('.modal-dialog').css('width', params['width']);//宽度
                }
                if (params['height']) {
                    modal.find('.modal-body').css('height', params['height']);    //高度
                }
                //垂直位置调整
                // modal.find('.modal-content').css("margin-top", 80);//固定值
                self._centerModals(modal);   //自动居中计算

                //流程属性内容
                modal.find('.modal-body').html(popHtml.html());
                //对数据进行处理
                self._initPopWin(modal, data,
                    function (popWin, data) {
                        return initFun(popWin, data);
                    });

                //确定和应用按钮事件绑定
                var applyBtn = modal.find('#applyBtn');
                applyBtn.off('click');//先解绑之前的事件
                applyBtn.on('click', function () {
                    self._applyPopWin(modal, data,
                        function (popWin, data) {
                            return applyFun(popWin, data);
                        });
                });

                modal.find('#okBtn').off('click');//先解绑之前的事件
                modal.find('#okBtn').on('click', function () {
                    if (!applyBtn.attr('disabled')) {
                        if (!self._applyPopWin(modal, data,
                            function (popWin, data) {
                                return applyFun(popWin, data);
                            })) {
                            return;
                        }
                    }
                    self._hidePopWin(popWin);
                    // popWin.modal('hide');
                });

            });

            popWin.modal({
                //backdrop: 'static', //禁用空白处点击关闭,这个地方不管用,放到页面上data-backdrop="static"
                keyboard: true,//ESC关闭
                show: true
            });

        },
        _hidePopWin: function (popWin) {
            if (!popWin) {
                popWin = $('#hzPopModal');
            }
            popWin.modal('hide');
        },
        _chgApplyBtn: function (applyBtn, disabled) {
            if (!applyBtn) {
                applyBtn = $('#applyBtn');
            }
            if (!disabled) {
                disabled = false;
            }
            applyBtn.attr('disabled', disabled);
        },
        _initPopWin: function (popWin, data, initFun) {
            var self = this;

            initFun(popWin, data);

            var applyBtn = popWin.find('#applyBtn');
            var allInput = popWin.find('.checkChange');
            allInput.on('change', function () {
                self._chgApplyBtn(applyBtn, false);
            });
        },
        _applyPopWin: function (popWin, data, applyFun) {
            var result = applyFun(popWin, data);
            if (result != "") {
                this.showMsg(result);
                return false;
            }
            this._chgApplyBtn(popWin.find('#applyBtn'), true);
            return true;
        },
        //属性框居中位置计算
        _centerModals: function (modal) {
            if (!modal) {
                modal = $('#hzPopModal');
            }
            modal.each(function (i) {
                var $clone = $(this).clone().css('display', 'block').appendTo('body');
                var top = Math.round(($clone.height() - $clone.find('.modal-content').height()) / 2);
                top = top > 0 ? top : 0;
                $clone.remove();
                $(this).find('.modal-content').css("margin-top", top);
            });
        },

        //=======菜单响应,流程属性框================================
        _showGeneralProperties: function () {
            alert("未开发");
        },

        _showProperties: function () {
            var data = this.curDrawLayer.data['flowInfo'];
            this._getFlowProperties().showProperties(data);
        },
        showJsonData: function (data) {
            var self = this;
            var text = JSON.stringify(data);
            this._popIframe(this.getLang('menu.showdata'),
                '<iframe id="ckJsonData" src="json/JSON-handle/JSON-handle.html" style="width:100%;height:550px;" />',
                '80%',
                function ($this) {
                    setTimeout(function () {
                        var target = $this.$content.find('#ckJsonData');
                        var frWin = target[0].contentWindow.document;
                        frWin.getElementById("enterValue").value = text;
                        //两个按钮一样效果
                        frWin.getElementById("jsObjEnterOk").click(); //jsObjEnterOk,enterOk
                    }, 5);
                }
            );
        },
        //获取示范代码
        showExampleJava: function (name, callback) {
            var path = 'data/' + this.localeVal + '/Example.java';
            this._popIframe(this.getLang('html.example'),
                '<iframe src="' + path + ' "style="width:100%;height:550px;" />', '80%'
            )
        },

        _popIframe: function (title, html, boxWidth, onContentReady) {
            var self = this;
            $.confirm({
                title: title ? title : self.getLang('static.info'),
                content: html,
                type: 'blue',
                icon: 'glyphicon glyphicon-info-sign',
                // columnClass: columnClass?columnClass:'small',
                boxWidth: boxWidth ? boxWidth : '50%',
                onContentReady: function () {
                    if (onContentReady) {
                        onContentReady(this);
                    }
                },
                useBootstrap: false,
                backgroundDismiss: false, //是否允许点击背景关闭
                buttons: {
                    ok: {
                        text: self.getLang('static.close'),
                        btnClass: 'btn-primary',
                        action: function () {
                        }
                    }
                }
            });
        },

        _refreshThisPage: function () {
            this.reloadFlowById(this.dataid);
            // window.location.reload();
        },
        //=============属性框中需要跟后端服务交互部分===================================
        isSaveFlow: true, //用来标记当前是否允许保存，默认允许，在新建流程修改flowid时会重置
        //------供属性页面调用------------------------
        //判断流程id是否存在
        checkFlowIdIsExistFromServer: function (flowId) {
            var self = this;
            var url = this.options.serverUrl + "checkflow" + this.options.suffix;
            var para = 'flowid=' + flowId;
            var msg = self.getLang('static.loaderror') + '<br>' + url + "?" + para;

            if (dev) {
                url = "/tmpdata/checkflow.json";
            }
            this._ajaxToServer(url, para, function (result) {
                if (result.result == 'err') {
                    self.isSaveFlow = false;
                    self.showMsg(result.msg);
                } else {
                    self.isSaveFlow = true;
                }
            }, msg);
        },
        //根据type获取自定义实现类
        _getCustomClassByType: function (type, callback) {
            var url = this.options.serverUrl + "findFlowRuleImpl" + this.options.suffix;
            var msg = this.getLang('static.loaderror') + '<br>' + url;
            var para = "type=" + type;
            if (dev) {
                url = "/tmpdata/getCustomClass.json";
            }
            this._ajaxToServer(url, para, callback, msg, false, false);
        },
        //根据type删除自定义实现类
        _delCustomClass: function (id, callback) {
            var url = this.options.serverUrl + "delFlowRuleImpl" + this.options.suffix;
            var msg = this.getLang('static.loaderror') + '<br>' + url;
            var para = "id=" + id;
            this._ajaxToServer(url, para, callback, msg);
        },
        //根据type获取自定义实现类
        _addCustomClass: function (para, callback) {
            var url = this.options.serverUrl + "addFlowRuleImpl" + this.options.suffix;
            var msg = this.getLang('static.loaderror') + '<br>' + url;
            this._ajaxToServer(url, para, callback, msg, true);
        },
        //获取所有的流程,用来进行流程选择
        _getFlowListFromServer: function (callback) {
            var url = this.options.serverUrl + "getFlowList" + this.options.suffix;
            var msg = this.getLang('static.loaderror') + '<br>' + url;

            if (dev) {
                url = "/tmpdata/getFlowList.json";
            }

            this._ajaxToServer(url, '', callback, msg);
        },
        //获取事件列表
        _getEventListFromServer: function (callback) {
            var url = this.options.eventlstUrl ? this.options.eventlstUrl : 'data/event.json';
            var msg = this.getLang('static.loaderror') + '<br>' + url;
            this._ajaxToServer(url, '', callback, msg);
        },

        //获取流程变量列表,用于子流程设置页面
        getSubFlowVarsFromServer: function (flowId, callback) {
            var url = this.options.serverUrl + "getFlowVar" + this.options.suffix;
            var para = 'flowid=' + flowId;
            var msg = this.getLang('static.loaderror') + '<br>' + url + "?" + para;

            if (dev) {
                url = "/tmpdata/getFlowVars.json";
            }

            this._ajaxToServer(url, para, callback, msg);
        },
        //从服务器获取流程分类
        getFlowTypeFromServer: function (callback) {
            var url = this.options.serverUrl + "getFlowType" + this.options.suffix;
            var para = '';
            var msg = this.getLang('static.loaderror') + '<br>' + url;

            if (dev) {
                url = "/tmpdata/getFlowType.json";
            }

            this._ajaxToServer(url, para, callback, msg);
        },
        //从服务器获取节点模版分类
        getNodeTypeFromServer: function (callback) {
            var url = this.options.serverUrl + "getNodeType" + this.options.suffix;
            var para = '';
            var msg = this.getLang('static.loaderror') + '<br>' + url;

            this._ajaxToServer(url, para, callback, msg);
        },
        //从服务器上获取指定类型的节点模版
        getNodeModuleLstFromServer: function (nodefix, callback) {
            var url = this.options.serverUrl + "getNodeModuleList" + this.options.suffix;
            var para = 'nodefix=' + nodefix;
            var msg = this.getLang('static.loaderror') + '<br>' + url + '?' + para;

            this._ajaxToServer(url, para, callback, msg);
        },
        //保存节点模版数据
        saveNodeModule: function (name, fix, type, data, rule, callback) {
            var self = this;
            var url = self.options.serverUrl + "saveNodeModule" + self.options.suffix;
            var para = 'name=' + name + '&fix=' + fix + '&type=' + type
                + '&data=' + encodeURIComponent(data) + '&rule=' + encodeURIComponent(rule);
            var msg = self.getLang('static.loaderror') + '<br>' + url + "?" + para;

            self._ajaxToServer(url, para, function (data) {
                callback(data);
            }, msg, true);
        },
        //删除节点模版数据
        _delNodeModule: function (mId, rId, callback) {
            var self = this;
            var url = self.options.serverUrl + "delNodeModule" + self.options.suffix;
            var para = 'mId=' + mId + '&rId=' + rId;
            var msg = self.getLang('static.loaderror') + '<br>' + url + "?" + para;

            self._ajaxToServer(url, para, function (data) {
                callback(data);
            }, msg, true, false);
        },
        //从服务器获取表单列表
        getFormsFromServer: function (callback) {
            var url = this.options.serverUrl + "getForms" + this.options.suffix;
            var para = '';
            var msg = this.getLang('static.loaderror') + '<br>' + url;

            if (dev) {
                url = "/tmpdata/getForms.json";
            }

            this._ajaxToServer(url, para, callback, msg);
        },
        //获取指定表单的数据(字段,按钮,字段权限)
        getFormInfoFromServer: function (formIds, formNames, tblObj) {
            if (!formIds) {
                return;
            }
            var url = this.options.serverUrl + "getFormInfo" + this.options.suffix;
            var para = 'formids=' + formIds;
            var msg = this.getLang('static.loaderror') + '<br>' + url + '?' + para;

            if (dev) {
                url = "/tmpdata/getFormInfo.json";
            }
            var self = this;
            this._ajaxToServer(url, para, function (data) {
                $.each(data.formInfo || [], function (id, item) {
                    if (item) {
                        item['name'] = formNames[id] || id;
                        self.curDrawLayer.forms[id] = item;
                    }
                });
                if (tblObj && tblObj.rows()[0] != undefined) {
                    tblObj.load(tblObj.rows());
                }
            }, msg);
        },
        //校验表单权限名称是否重复
        checkFormAuthNameToServer: function (id, name, formId, callback) {
            var url = this.options.serverUrl + "checkFormAuthName" + this.options.suffix;
            var msg = this.getLang('static.loaderror') + '<br>' + url;

            if (dev) {
                url = "/tmpdata/saveFormField.json";
            }
            var self = this;
            this._ajaxToServer(url, {id: id, name: name, formId: formId}, function (data) {
                callback(data);
            }, msg, true, false);
        },
        //保存字段权限到服务器
        saveFormFieldAuthToServer: function (data, callback) {
            var url = this.options.serverUrl + "saveFormField" + this.options.suffix;
            var para = 'data=' + encodeURIComponent(JSON.stringify(data));
            var msg = this.getLang('static.loaderror') + '<br>' + url + '?' + para;

            if (dev) {
                url = "/tmpdata/saveFormField.json";
            }
            var self = this;
            this._ajaxToServer(url, para, function (data) {
                callback(data);
            }, msg, true, false);
        },

        //存放组织ID和中文对应值
        orgCnNames: {},
        _pushToCnNames: function (data, label) {
            var orgs = data.split('/');
            var txt = label.split('/');
            this.orgCnNames[data] = label;
            //拆分后存放
            if (orgs.length > 1) {
                this.orgCnNames[orgs[0]] = txt[0];
                this.orgCnNames[orgs[1]] = txt[1];
            }
        },
        //从orgCnNames中获取id对应的中文名
        getCnName: function (id) {
            var pos = id.indexOf('_');
            if (pos <= 2) {
                id = id.substring(pos + 1);
            }
            /* 增加了部门接口人DJ负责人DF领导人DL的标识，所以改为上面的处理
            if(id.startsWith('_',1)){
                id = id.substring(2);
            }
            //*/
            return this.orgCnNames[id];

        },
        //从服务器上获取人员id对应的中文名称,用于显示
        _getOrgNameFromServer: function (orgs, callback, async) {
            var url = this.options.serverUrl + "getOrgName" + this.options.suffix;
            var para = 'orgs=' + JSON.stringify(orgs);

            var self = this;
            if (dev) {
                url = '/tmpdata/getOrgName.json';
            }
            var msg = this.getLang('static.loaderror') + '<br>' + url + '?' + para;
            this._ajaxToServer(url, para, function (data) {
                var cn = data.orgs;
                $.each(cn || [], function (key, value) {
                    if (value) {
                        self._pushToCnNames(key, value);
                    }
                });
                callback();
            }, msg, !dev, async);
        },
        //从服务器上获取规则页面信息和保存规则信息
        _getRuleByIDFromServer: function (ruleId, callback) {
            var url = this.options.serverUrl + "getRuleById" + this.options.suffix;
            var para = 'id=' + ruleId;
            var msg = this.getLang('static.loaderror') + '<br>' + url + '?' + para;

            var self = this;
            this._ajaxToServer(url, para, function (data) {
                var rule = data.rule;
                callback(rule);
            }, msg);
        },
        /*
        _saveRuleToServer:function(data,callback){
            var url = this.options.serverUrl + "saveRule" + this.options.suffix;
            var html = data.html;
            delete data['html'];
            var para = 'data='+JSON.stringify(data) +'&html='+encodeURIComponent(html);
            var msg = this.getLang('static.loaderror') + '<br>' + url +'?'+para;
            var self = this;
            this._ajaxToServer(url, para, function (data) {
                callback(data);
            }, msg,true,false);
        },
        //*/
        //================弹出框===============================
        //显示一些提示信息
        // type 0：成功 1：失败 2：警告
        showMsg: function (msg, title, callback, type) {
            var self = this;
            var icon = type != 0 ? type != 1 ? 'question' : 'info' : 'ok'
            $.confirm({
                title: title ? title : self.getLang('static.info'),
                content: msg,
                type: type == 0 ? 'blue' : 'red',
                icon: 'glyphicon glyphicon-' + icon + '-sign',
                backgroundDismiss: true, //是否允许点击背景关闭
                buttons: {
                    ok: {
                        text: self.getLang('static.ok'),
                        btnClass: 'btn-primary',
                        action: function () {
                            if (callback) {
                                callback();
                            }
                        }
                    }
                }
            });
        },
        //用于询问
        applyQuestion: function (msg, callback) {
            var self = this;
            $.confirm({
                title: this.getLang('static.warning'),
                content: msg,
                type: 'red',
                icon: 'glyphicon glyphicon-question-sign',
                backgroundDismiss: false, //是否允许点击背景关闭
                buttons: {
                    ok: {
                        text: self.getLang('static.ok'),
                        btnClass: 'btn-primary',
                        action: function () {
                            if (callback) {
                                callback();
                            }
                        }
                    },
                    cancel: {
                        text: this.getLang('static.cancel'),
                        btnClass: 'btn-primary'
                    }
                }
            });
        },
        //用于选择返回
        popSelWin: function (title, msg, callback, boxWidth, okName, onContentReady, showModal, cancelBack, cancelName) {
            var self = this;
            $.confirm({
                title: title ? title : self.getLang('static.info'),
                content: msg,
                type: 'blue',
                icon: 'glyphicon glyphicon-info-sign',
                // columnClass: columnClass?columnClass:'small',
                boxWidth: boxWidth ? boxWidth : '350px',
                onContentReady: function () {
                    if (onContentReady) {
                        onContentReady(this);
                    }
                },
                useBootstrap: false,
                backgroundDismiss: false, //是否允许点击背景关闭
                buttons: {
                    ok: {
                        text: okName ? okName : self.getLang('static.ok'),
                        btnClass: 'btn-primary',
                        action: function () {
                            if (callback) {
                                return callback(this.$content, this);
                            }
                        }
                    },
                    cancel: {
                        text: cancelName ? cancelName : self.getLang('static.cancel'),
                        btnClass: 'btn-primary',
                        action: function () {
                            if (showModal) {
                                $('#hzPopModal').show();
                            }
                            if (cancelBack) {
                                return cancelBack(this);
                            }
                        }
                    }
                }
            });
        },

        //================属性框需要用到到一些共用方法==================================
        updateChgFlowName: function (data, oldName) {
            this._chgStatusTitle(data);

            //泳道标题,如果跟流程名称一致,则修改,否则不修改
            if (this.curDrawLayer._swimlane) {
                if (oldName == this.curDrawLayer._swimlane.name) {
                    this.curDrawLayer._swimlane.setSwimlaneTitle(data.flowName);
                }
            }
        },
        initOrgData: function (userdata, userOrg, tblObjArr, key, height, async, callback) {
            /*
            var self = this;
            var orgTypes = this.options.orgTypes;
            var items = [];
            //数据初始化
            var orgs = {};
            $.each(userdata || [],function(key,item){
                //从json数据中的participants节点获取,下面的标示不要修改,
                if(item &&(key == 'person' || key == 'dept' || key == 'group' || key == 'position')){
                    $.each(item.split(";") || [], function (i, org) {
                        if(org){
                            //org 拆分
                            if(key =='person'){
                                self._splitOrg(orgs,org);
                            }
                            else{
                                var index = org.indexOf('_');
                                self._pushToJson(orgs,key,org.substring(index+1));
                            }
                            items.push({
                                data: org,
                                label: org,
                                typeCn: orgTypes[key],
                                type:key
                            });
                        }
                    });
                }
            });
            this._initOrgNamesFromServer(orgs,function(){
                // callback(items);
                //userOrg 标签内的表格对象获取
                var tblUserOrg = userOrg.find('#tblUserOrg').mmGrid({
                    height: height
                    , cols: self._getUserOrgTableCol()
                    , items: items      //本地数据
                    , nowrap:true
                    , multiSelect: true
                    , fullWidthRows: true
                    , autoLoad: false
                    , loadingText:self.getLang('html.org.load')
                    , noDataText:self.getLang('html.org.nodata')
                });
                tblUserOrg
                    .on('cellSelected', function (e, item, rowIndex, colIndex) {
                        if ($(e.target).is('.selBtn')) {
                            e.stopPropagation(); //阻止事件冒泡
                            var d = item.data;
                            var label = '';
                            var title = self.getLang('html.org.title');
                            if(d.startsWith('D_')){
                                d = 'S'+d.substring(1);
                                label = title[4];
                            }
                            else{
                                d = 'D'+d.substring(1);
                                label = title[3];
                            }
                            item.data = d;
                            $(e.target).html(label);
                            tblUserOrg.updateRow(item,rowIndex);
                            self._chgApplyBtn();
                        }
                    })
                    .on('loadSuccess',function(e, data){
                        userOrg.find('.deptTypeSel').on('change',function(){
                            var rowIndex = $(this).parent().parent().parent().index();
                            var item = tblUserOrg.row(rowIndex);
                            var tmp = item.data;
                            var pos = tmp.indexOf('_') + 1;
                            item.data= $(this).val() +'_' + tmp.substring(pos);
                            tblUserOrg.load(tblUserOrg.rows());
                            self._chgApplyBtn($('#applyBtn'), false);
                        });
                    })
                    .load();
                tblObjArr[key] = tblUserOrg;
                //按钮事件绑定
                userOrg.find('#btnOrgAdd').on('click',function(){
                    var org = {data:'',label:''};
                    $.each(tblUserOrg.rows() || [],function(i,item){
                       if(item){
                           org['data'] += item.data +';';
                           org['label'] += item.label +';';
                       }
                    });

                    $('#hzPopModal').hide();
                    selectUser(org,function(data){
                        if(data){
                            var ids = data.data.split(';');
                            var name = data.label.split(';');
                            var items = [];
                            var keys ={
                                U:'person',
                                D:'dept',
                                S:'dept',
                                G:'group',
                                P:'position'
                            };
                            $.each(ids || [],function(i,value){
                                if(!value){return self.CONTINUE;} //continue
                                //是否有前缀，如果没有默认为U
                                var pos = value.indexOf('_');
                                var key = keys['U'];
                                if(pos == 1){
                                    key = keys[value.substring(0,1)];//获取前缀对应的标识
                                    value = value;//.substring(2);      //重置value值
                                }
                                items.push({
                                    data: value,
                                    label: name[i],
                                    typeCn: orgTypes[key],
                                    type:key
                                });
                                //选择后的组织信息缓存到orgCnNames中
                                self._pushToCnNames(value,name[i]);

                            });
                        }
                        tblUserOrg.load(items);
                        self._chgApplyBtn();
                        $('#hzPopModal').show();
                    });

                });
                userOrg.find('#btnOrgDel').on('click',function(){
                    if(self.delCheckSel(tblUserOrg)){
                        return;
                    }
                    self.applyQuestion(self.getLang('html.org.del'),function() {
                        tblUserOrg.removeRow(tblUserOrg.selectedRowsIndex());
                        self._chgApplyBtn($('#applyBtn'), false);
                    });
                });
                userOrg.find('#btnOrgDelAll').on('click',function(){
                    self.applyQuestion(self.getLang('html.org.delAll'),function() {
                        tblUserOrg.removeRow();
                        self._chgApplyBtn($('#applyBtn'), false);
                    });
                });
            },async);
            //*/
            this.initOrgDataTable(userOrg, tblObjArr, key, height, callback);
            this.initOrgDataItem(userdata, tblObjArr, key, async);
        },
        initOrgDataTable: function (userOrg, tblObjArr, key, height, callback) {
            var self = this;
            var orgTypes = this.options.orgTypes;
            var tblUserOrg = userOrg.find('#tblUserOrg').mmGrid({
                height: height
                , delTitle: self.getLang('table.field.defTitle')
                , showCol: self.getLang('table.field.showCol')
                , cols: self._getUserOrgTableCol()
                , items: []      //本地数据
                , nowrap: true
                , multiSelect: true
                , fullWidthRows: true
                , autoLoad: false
                , loadingText: self.getLang('html.org.load')
                , noDataText: self.getLang('html.org.nodata')
            });
            tblUserOrg
                .on('cellSelected', function (e, item, rowIndex, colIndex) {
                    if ($(e.target).is('.selBtn')) {
                        e.stopPropagation(); //阻止事件冒泡
                        var d = item.data;
                        var label = '';
                        var title = self.getLang('html.org.title');
                        if (d.startsWith('D_')) {
                            d = 'S' + d.substring(1);
                            label = title[4];
                        } else {
                            d = 'D' + d.substring(1);
                            label = title[3];
                        }
                        item.data = d;
                        $(e.target).html(label);
                        tblUserOrg.updateRow(item, rowIndex);
                        self._chgApplyBtn();
                    }
                })
                .on('loadSuccess', function (e, data) {
                    userOrg.find('.deptTypeSel').on('change', function () {
                        var rowIndex = $(this).parent().parent().parent().index();
                        var item = tblUserOrg.row(rowIndex);
                        var tmp = item.data;
                        var pos = tmp.indexOf('_') + 1;
                        item.data = $(this).val() + '_' + tmp.substring(pos);
                        tblUserOrg.load(tblUserOrg.rows());
                        if (callback) {
                            callback();
                        }
                        self._chgApplyBtn($('#applyBtn'), false);
                    });
                })
                .load();
            tblObjArr[key] = tblUserOrg;
            //按钮事件绑定
            userOrg.find('#btnOrgAdd').on('click', function () {
                var org = {data: '', label: ''};
                $.each(tblUserOrg.rows() || [], function (i, item) {
                    if (item) {
                        org['data'] += item.data + ';';
                        org['label'] += item.label + ';';
                    }
                });

                $('#hzPopModal').hide();
                selectUser(org, function (data) {
                    if (data) {
                        var ids = data.data.split(';');
                        var name = data.label.split(';');
                        var items = [];
                        var keys = {
                            U: 'person',
                            D: 'dept',
                            S: 'dept',
                            G: 'group',
                            P: 'position'
                        };
                        $.each(ids || [], function (i, value) {
                            if (!value) {
                                return self.CONTINUE;
                            } //continue
                            //是否有前缀，如果没有默认为U
                            var pos = value.indexOf('_');
                            var key = keys['U'];
                            if (pos >= 1) {
                                key = keys[value.substring(0, 1)];//获取前缀对应的标识
                                value = value;//.substring(2);      //重置value值
                            }
                            items.push({
                                data: value,
                                label: name[i],
                                typeCn: orgTypes[key],
                                type: key
                            });
                            //选择后的组织信息缓存到orgCnNames中
                            self._pushToCnNames(value, name[i]);

                        });
                    }
                    tblUserOrg.load(items);
                    if (callback) {
                        callback('add');
                    }
                    self._chgApplyBtn();
                    $('#hzPopModal').show();
                });

            });
            userOrg.find('#btnOrgDel').on('click', function () {
                if (self.delCheckSel(tblUserOrg)) {
                    return;
                }
                self.applyQuestion(self.getLang('html.org.del'), function () {
                    tblUserOrg.removeRow(tblUserOrg.selectedRowsIndex());
                    if (callback) {
                        callback('del');
                    }
                    self._chgApplyBtn($('#applyBtn'), false);
                });
            });
            userOrg.find('#btnOrgDelAll').on('click', function () {
                self.applyQuestion(self.getLang('html.org.delAll'), function () {
                    tblUserOrg.removeRow();
                    if (callback) {
                        callback('delAll');
                    }
                    self._chgApplyBtn($('#applyBtn'), false);
                });
            });
        },
        initOrgDataItem: function (userdata, tblObjArr, key, async) {
            var self = this;
            var orgTypes = this.options.orgTypes;
            var items = [];
            //数据初始化
            var orgs = {};
            $.each(userdata || [], function (key, item) {
                //从json数据中的participants节点获取,下面的标示不要修改,
                if (item && (key == 'person' || key == 'dept' || key == 'group' || key == 'position')) {
                    $.each(item.split(";") || [], function (i, org) {
                        if (org) {
                            //org 拆分
                            if (key == 'person') {
                                self._splitOrg(orgs, org);
                            } else {
                                var index = org.indexOf('_');
                                self._pushToJson(orgs, key, org.substring(index + 1));
                            }
                            items.push({
                                data: org,
                                label: org,
                                typeCn: orgTypes[key],
                                type: key
                            });
                        }
                    });
                }
            });
            this._initOrgNamesFromServer(orgs, function () {
                // callback(items);
                //userOrg 标签内的表格对象获取
                tblObjArr[key].load(items);
            }, async);
        },
        _getUserOrgTableCol: function () {
            var self = this;
            var title = this.getLang('html.org.title');
            var deptTypes = this.getOptions('deptTypes');

            var selHtml = function (sel) {
                var tmpHtml = '<select style="width:80px" class="deptTypeSel">';
                $.each(deptTypes || [], function (data, label) {
                    tmpHtml += '<option value="' + data + '" ' + (sel == data ? 'selected="selected"' : '') + '>' + label + '</option>';
                });
                tmpHtml += '</select>';
                return tmpHtml;
            }

            return [
                {
                    title: title[0],//'组织名称',
                    name: 'label',
                    width: 238,
                    sortable: true,
                    align: 'left',
                    renderer: function (val, item, rowIndex) {
                        if (val == item.data) {
                            //直接查找一次，如果存在说明是刚选择的组织（没有保存重新打开流程时）
                            var label = self.getCnName(val);
                            if (!label) {
                                //如果没有值，则继续拆分查找
                                var orgs = val.split('/');
                                var suf = '';
                                if (orgs.length > 1) {
                                    suf = ('(' + self.getCnName(orgs[1]) + ')');
                                }

                                label = self.getCnName(orgs[0]) + suf;
                            }

                            item.label = label;
                            return label;
                        } else {//从前台选择返回时,不需要组合
                            return val;
                        }
                    }
                },
                {
                    title: title[1],//'组织ID',
                    name: 'data',
                    width: 220,
                    sortable: true,
                    align: 'center',
                    renderer: function (val, item, rowsIndex) {
                        return '<span title="' + val + '">' + val + '</span>';
                    }
                },
                {
                    title: title[2],//'类型',
                    name: 'typeCn',
                    width: 150,
                    sortable: true,
                    align: 'center',
                    renderer: function (val, item, rowsIndex) {
                        var html = val;
                        var data = item['data'];
                        var sel = data.substring(0, data.indexOf('_'));
                        if (data.startsWith('S') || data.startsWith('D')) {
                            //html = '<button class="btn btn-info btn-sm pull-right selBtn">'+title[4]+'</button>';
                            html = selHtml(sel);
                        }

                        return html;
                    }
                }
            ];
        },
        _initOrgNamesFromServer: function (orgs, callback, async) {
            var self = this;
            var tmpOrg = {};//仍然需要去server端获取中文的组织id
            $.each(orgs || [], function (key, org) {
                $.each(org || [], function (i, id) {
                    if (id && !self.getCnName(id)) {//从orgCnNames中获取中文名称
                        self._pushToJson(tmpOrg, key, id);
                    }
                });

            });
            if (!$.isEmptyObject(tmpOrg)) {
                self._getOrgNameFromServer(tmpOrg, callback, async);
            } else {
                callback();
            }
        },
        //拆分组织,用于获取中文名称
        _splitOrg: function (result, org) {
            var orgs = org.split('/');
            this._pushToJson(result, 'person', orgs[0]);

            if (orgs.length > 1) {
                var subject = orgs[1].split('_');
                var preSuf = '';
                if (subject[0] == 'D' || subject[0] == 'S') {
                    preSuf = 'dept';
                } else if (subject[0] == 'G') {
                    preSuf = 'group';
                } else if (subject[0] == 'P') {
                    preSuf = 'position';
                } else {
                    preSuf = 'other';
                }
                this._pushToJson(result, preSuf, subject[1]);
            }

            return result;
        },
        _pushToJson: function (json, key, value) {
            if (!json[key]) {
                json[key] = [];
            }
            if (json[key].indexOf(value) == -1) {
                if (value.startsWith('_', 1)) {
                    json[key].push(value.substring(2));
                } else {
                    json[key].push(value);
                }

            }
        },

        delCheckSel: function (tblObj) {
            var select = tblObj.selectedRowsIndex();
            if (select.length == 0) {
                this.showMsg(this.getLang('static.delcksel'));
                return true;
            }
            return false;
        },

        //实现类和规则,二选一的互斥事件
        bindRuleOrClass: function (node, popWin, name, data, returnType) {
            var self = this;
            //初始化时
            var value = data['className'] || '', script = data['script'] || '';
            var className = popWin.find('input[name="' + name + 'ClassName"]');
            className.val(value);
            self._chgRuleOrClass(popWin, name, value, script, true);

            //为了避免事件被重复绑定,所以需要先解绑
            className.off('blur');
            className.on('blur', function () {
                self._chgRuleOrClass(popWin, name, this.value);
            });

            self.onlyBindRule(node, popWin, name, data, true, returnType);
        },

        onlyBindRule: function (node, popWin, name, data, chgClass, returnType) {
            var self = this;
            var ruleId = popWin.find('input[name="' + name + 'RuleId"]');
            var ruleScript = popWin.find('textarea[name="' + name + 'RuleScript"]');
            var ruleText = popWin.find('textarea[name="' + name + 'RuleText"]');
            //下面两个属性是被隐藏的
            ruleId.val(data['id'] || '');
            ruleScript.val(data['script'] || '');
            ruleText.val(data['text'] || ''); // text 值可能需要转换

            var editBtn = popWin.find('#btnEdit' + this._firstUppcase(name) + 'Rule');
            editBtn.off('click');
            editBtn.on('click', function () {
                //判断如果是实例修改,则不允许
                // if(self.showtype !=1){
                //     self.showMsg('规则是存储在库表中的,不允许在实例修改状态下修改');
                // }todottodo
                var oldRule = {
                    id: ruleId.val(),
                    script: ruleScript.val(),
                    text: ruleText.val(),
                    returnType: returnType || 'boolean'
                };

                //TODO 规则调用参数
                HorizonWorkflow.nodeId = node ? node.id : '';
                HorizonWorkflow.forminfo = getAllFormsInfo();
                HorizonWorkflow.flowinfo = getAllFlowsInfo();
                HorizonWorkflow.html = '';

                if (oldRule.id != '') {
                    //先从缓存中获取
                    var tmpRule = self.curDrawLayer.rules[oldRule.id];
                    if (tmpRule) {
                        HorizonWorkflow.html = (tmpRule.html);
                        self._openEidtRule(popWin, name, oldRule, chgClass);
                    } else {
                        //从后端获取对应的html内容
                        self._getRuleByIDFromServer(oldRule.id, function (rule) {
                            if (rule && rule.html) {
                                HorizonWorkflow.html = (rule.html);
                                self._openEidtRule(popWin, name, oldRule, chgClass);
                            } else {
                                self._openEidtRule(popWin, name, oldRule, chgClass);
                            }
                        });
                    }
                } else {
                    self._openEidtRule(popWin, name, oldRule, chgClass);
                }
            });

            var getAllFormsInfo = function () {
                var forms = self.curDrawLayer.data['flowInfo']['forms'];
                if (forms) {
                    var formInfos = '';
                    $.each(forms || [], function (id, form) {
                        if (form && id != 'FlowTrack') {
                            formInfos += ';' + form.id + ':' + form.name;
                        }
                    });
                    if (formInfos != '') {
                        return formInfos.substring(1);
                    }
                }
                return '';
            };
            var getAllFlowsInfo = function () {
                //因为第一个就是表单信息,在规则页面中没有使用,此处不获取
                var nodes = '';
                var nodeObj = self.curDrawLayer._nodes;
                if (nodeObj) {
                    $.each(nodeObj || [], function (id, node) {
                        if (node) {
                            nodes += '~' + node.id + '=' + node.name;
                        }
                    });
                    if (nodes != '') {
                        nodes = nodes.substring(1);
                    }
                }
                var vars = '';
                var varObj = self.curDrawLayer.data.flowInfo['vars'];
                if (varObj) {
                    $.each(varObj || [], function (id, item) {
                        if (item) {
                            vars += '~' + item.varId + '=' + item.varName;
                        }
                    });
                    if (vars != '') {
                        vars = vars.substring(1);
                    }
                }

                return ';' + nodes + ';' + vars;
            };

        },

        _openEidtRule: function (popWin, name, data, chgClass) {
            var self = this;
            var returnType = data['returnType'] || '';
            var url = self.options.ruleEditorPage + '?returnType=' + returnType;
            var html = '<iframe id="popSel" src="' + url + '" style="border:none;width:100%;height: 550px;"/>';
            $.confirm({
                title: false, closeIcon: false,
                content: html,
                type: 'blue',
                boxWidth: '800px',
                useBootstrap: false,
                backgroundDismiss: false, //是否允许点击背景关闭
                buttons: {
                    ok: {
                        text: self.getLang('static.ok'),
                        btnClass: 'btn-primary',
                        action: function () {
                            return editRuleOk(this.$content, popWin, name, chgClass, data);
                        }
                    },
                    clear: {
                        text: self.getLang('static.clearRule'),//'清除',
                        btnClass: 'btn-primary',
                        action: function () {
                            editRuleApply(popWin, name, chgClass, {id: '', script: '', text: ''});
                        }
                    },
                    cancel: {
                        text: self.getLang('static.cancel'),
                        btnClass: 'btn-primary',
                        action: function () {
                        }
                    }
                }
            });
            //点击确定时执行
            var editRuleOk = function ($this, popWin, name, chgClass, data) {
                // 需要把数据存入到库表中
                var ruleWin = $this.find('#popSel')[0].contentWindow;
                // 判断规则是否完整
                var ck = ruleWin.ckValidityInfo();
                if (ck != "") {
                    // self.showMsg(ck); //iframe页面会弹出提示窗口
                    return false;
                }
                //回写结果
                var code = ruleWin.getCodeResult();
                var codeCN = ruleWin.getCodeCNResult();
                var codeHtml = ruleWin.getCodeHtml();
                var codeId = data['id'] == "" ? self._getUNID() : data['id'];

                //临时存储
                var tmpRule = {
                    id: codeId,
                    oldId: data['id'],
                    flowid: self.flowid,//流程id总是有的
                    workid: self.showtype == 5 ? self.dataid : '',//实例编辑时
                    html: codeHtml
                };
                if (self.showtype == 5) {
                    tmpRule['id'] = self._getUNID(); //实例修改时,每次都生成新的id
                    delete self.curDrawLayer.rules[codeId];//避免多次修改
                }

                self.curDrawLayer.rules[tmpRule.id] = tmpRule;
                editRuleApply(popWin, name, chgClass, {
                    id: tmpRule.id,
                    script: code,
                    text: codeCN
                });
                return true;

            };

            var editRuleApply = function (popWin, name, chgClass, rule) {
                var ruleId = popWin.find('input[name="' + name + 'RuleId"]');
                var ruleScript = popWin.find('textarea[name="' + name + 'RuleScript"]');
                var ruleText = popWin.find('textarea[name="' + name + 'RuleText"]');

                if (rule['id'] == '') {
                    //删除规则标记
                    var id = ruleId.val();
                    if (id && id != '') {
                        var tmpRule = self.curDrawLayer.rules[id];
                        if (tmpRule) {
                            tmpRule.html = '';
                        } else {
                            self.curDrawLayer.rules[id] = {
                                id: id,
                                html: ''
                            }
                        }
                    }
                }
                ruleId.val(rule['id']);
                ruleScript.val(rule['script']);
                ruleText.val(rule['text']);

                if (chgClass) {
                    self._chgRuleOrClass(popWin, name, '', rule['script']);
                } else {
                    self._chgApplyBtn();
                }
            };
        },

        _chgRuleOrClass: function (popWin, name, value, script, save) {
            if (value && value != '') {
                popWin.find('#btnEdit' + this._firstUppcase(name) + 'Rule').attr('disabled', true);
                popWin.find('textarea[name="' + name + 'RuleText"]').attr('disabled', true);
            } else {
                popWin.find('#btnEdit' + this._firstUppcase(name) + 'Rule').removeAttr('disabled');
                popWin.find('textarea[name="' + name + 'RuleText"]').removeAttr('disabled');

                if (script && script != '') {
                    popWin.find('input[name="' + name + 'ClassName"]').attr('disabled', true);

                } else {
                    popWin.find('input[name="' + name + 'ClassName"]').removeAttr('disabled');
                }
            }
            if (!save) {
                this._chgApplyBtn($('#applyBtn'), false);
            }
        },
        _firstUppcase: function (str) {
            var first = str.substring(0, 1);
            return first.toUpperCase() + str.substring(1);
        },

        //从后端获取32位ID
        Unids: [],
        _getUNID: function () {
            var self = this;
            if (self.Unids.length == 0) {
                var url = this.options.serverUrl + "getUnids" + this.options.suffix;
                var para = '';
                var msg = this.getLang('static.loaderror') + '<br>' + url;
                if (dev) {
                    url = "/tmpdata/getUnids.json";
                }
                this._ajaxToServer(url, para, function (data) {
                    self.Unids = data['Unids'];
                }, msg, null, false);
            }
            return self.Unids.shift();//返回第一并删除,pop返回最后一个并删除
        },
        _makeNewRule: function (rule, drawLayer, del) {
            var id = this._getUNID();
            var oldId = rule.id;
            var tmpRule = {
                id: id,
                oldId: oldId,
                flowid: this.flowid,//流程id总是有的
                workid: this.showtype == 5 ? this.dataid : '',//实例编辑时
                html: ''
            };

            //看看未保存的规则在列表中是否存在
            var oldRule = drawLayer.rules[oldId];
            if (oldRule) {
                tmpRule['html'] = oldRule['html'];
                if (del) {
                    delete drawLayer.rules[oldId];//复制流程时
                }
            }
            rule['id'] = id; //更新JSON数据中的id
            return tmpRule;
        },
        _copyRule: function (rule, drawLayer, del) {
            var tmpRule = this._makeNewRule(rule, drawLayer, del);
            drawLayer.rules[tmpRule.id] = tmpRule;
            return tmpRule;
        },
        //复制节点或者流程时,规则内存的复制
        copyNodeRule: function (newData, drawLayer, del) {
            var self = this;
            var participants = newData.participants;
            if (participants) {
                $.each(participants, function (key, participant) {
                    if (participant) {
                        var rule = participant['rule'];
                        if (rule && rule.id) {
                            self._copyRule(rule, drawLayer, del);
                        }
                    }
                });
            }
            var entry = newData.entry;
            if (entry && entry.id) {
                self._copyRule(entry, drawLayer, del);
            }
            var leave = newData.leave;
            if (leave && leave.id) {
                self._copyRule(leave, drawLayer, del);
            }

            //路由条件
            var transitions = newData.transitions;
            if (transitions) {
                $.each(transitions, function (key, transition) {
                    if (transition) {
                        var rule = transition['rule'];
                        if (rule && rule.id) {
                            self._copyRule(rule, drawLayer, del);
                        }
                    }
                });
            }
        },
        //节点存为模版时,规则内容复制
        copyRuleModule: function (newData, drawLayer) {
            var self = this;
            var rules = [];
            var participants = newData.participants;
            if (participants) {
                $.each(participants, function (key, participant) {
                    if (participant) {
                        var rule = participant['rule'];
                        if (rule && rule.id) {
                            rules.push(self._makeNewRule(rule, drawLayer, false));
                        }
                    }
                });
            }
            var entry = newData.entry;
            if (entry && entry.id) {
                rules.push(self._makeNewRule(entry, drawLayer, false));
            }
            var leave = newData.leave;
            if (leave && leave.id) {
                rules.push(self._makeNewRule(leave, drawLayer, false));
            }

            return rules;
        },
        //删除节点时,删除规则内容
        delNodeRule: function (data, drawLayer) {
            var self = this;
            var delRule = function (id) {
                var oldRule = drawLayer.rules[id];
                if (!oldRule) {
                    oldRule = {
                        id: id,
                        oldId: '',
                        html: ''
                    }
                    drawLayer.rules[id] = oldRule;
                } else {
                    oldRule.html = '';
                    oldRule.oldId = '';
                }
            };
            var participants = data.participants;
            if (participants) {
                $.each(participants, function (key, participant) {
                    if (participant) {
                        var rule = participant['rule'];
                        if (rule && rule.id) {
                            delRule(rule.id);
                        }
                    }
                });
            }
            var entry = data.entry;
            if (entry && entry.id) {
                delRule(entry.id);
            }
            var leave = data.leave;
            if (leave && leave.id) {
                delRule(leave.id);
            }

            //路由条件
            var transitions = data.transitions;
            if (transitions) {
                $.each(transitions, function (key, transition) {
                    if (transition) {
                        var rule = transition['rule'];
                        if (rule && rule.id) {
                            delRule(rule.id);
                        }
                    }
                });
            }
        },
        //获取规则配置内容
        getRuleValue: function (popWin, name) {
            var className = popWin.find('input[name="' + name + 'ClassName"]').val();
            if (className != '') {
                return {
                    className: className,
                    script: ''
                };
            } else {
                var script = popWin.find('textarea[name="' + name + 'RuleScript"]').val();
                if (script != '') {
                    return {
                        className: '',
                        id: popWin.find('input[name="' + name + 'RuleId"]').val(),
                        script: script,
                        text: popWin.find('textarea[name="' + name + 'RuleText"]').val()
                    };
                }
            }
            return {className: '', script: ''};
        },

        //根据流程分类文本,拆分成树需要的层级对象
        initTreeData: function (data, defVal, clickFun) {
            var self = this;
            var treeObj = [];
            $.each(data || [], function (i, item) {
                if (!item) {
                    return self.CONTINUE;
                }
                var type = '';
                var selFlow = true; //true选择流程.false选择类型
                //需要判断item是否为对象
                if (typeof item == 'string') {
                    //用于选择分类时
                    type = item;
                    selFlow = false;
                } else {
                    type = item.type;
                }

                if (type == null || type == undefined || type == '') {
                    var tmpObj1 = self._getFlowTypeObj(treeObj, self.getLang('static.nogroup'), true, clickFun);
                    if (selFlow && !self._checkDataExist(tmpObj1['data'], item.id)) {
                        tmpObj1['data'].push(item);
                    }
                    return self.CONTINUE;//continue
                }
                var checked = type == defVal || !defVal;
                var ss = type.split('/');

                var tmpObj = self._getFlowTypeObj(treeObj, ss[0], checked, clickFun);//从第一级开始
                if (selFlow && !self._checkDataExist(tmpObj['data'], item.id)) {
                    tmpObj['data'].push(item);
                }

                $.each(ss || [], function (i, val) {
                    if (i == 0 || val == '') {
                        return self.CONTINUE;//continue
                    }
                    var curObj = self._getFlowTypeObj(tmpObj['children'], val, checked, clickFun);
                    if (selFlow && !self._checkDataExist(curObj['data'], item.id)) {
                        curObj['data'].push(item)
                    }
                    tmpObj = curObj;
                });
            });
            return treeObj;

        },
        //多级分类结构树的数据,判断指定label是否已经存在,如果不存在则创建一个,否则返回
        _getFlowTypeObj: function (list, label, checked, clickFun) {
            var tmpObj = null;
            var self = this;
            $.each(list || [], function (i, item) {
                if (item && item["name"] == label) {
                    tmpObj = item;
                    return self.BREAK;
                }
            });
            if (tmpObj != null) {
                if (checked) {
                    tmpObj.open = true;
                }
                return tmpObj;
            }
            //如果没有,则创建一个
            tmpObj = {
                name: label,     //树需要的
                children: [],    //树的子节点列表
                open: checked,      //是否打开
                click: clickFun,
                data: []         //自定义的
            };

            list.push(tmpObj);

            return tmpObj;
        },
        //判断节点下的数据对象是否存在
        _checkDataExist: function (list, name) {
            var isHave = false;
            var self = this;
            $.each(list || [], function (i, item) {
                if (item && item['id'] == name) {
                    isHave = true;
                    return self.BREAK; //break;
                }
            });
            return isHave;
        },
        //只允许输入数字的校验
        checkInputOnlyNumber: function ($this, len) {
            var temp_amount = $this.val();
            if (/[^\d]/.test($this.val())) {//替换非数字字符
                temp_amount = $this.val().replace(/[^\d]/g, '');
            }
            if (temp_amount.length > len) {
                temp_amount = temp_amount.substring(0, len);
            } else if (temp_amount == '') {
                temp_amount = '0';
            }
            $this.val(parseInt(temp_amount));
        },

        //字母和数字校验
        checkInputCharNumber: function ($this, len) {
            var temp = $this.val().replace(/[^\w]/ig, ''); //[A-Za-z0-9]   ///[^\w]/ig

            var reg = RegExp('^[a-zA-Z_]');
            var first = temp.substring(0, 1);
            while (!(reg.test(first) || first == '')) {
                //开头为数字时,删除
                temp = temp.substring(1);
                first = temp.substring(0, 1);
            }

            if (temp.length > len) {
                temp = temp.substring(0, len);
            }
            $this.val(temp);
        },

        //仅限制长度
        checkInputLen: function ($this, len) {
            if ($this.val().length > len) {
                $this.val($this.val().substring(0, len));
            }
        },

        checkAndChange: function (obj, checkFun, checkPara, callback) {
            var self = this;
            obj.off('keyup');
            obj.on('keyup', function () {
                self[checkFun]($(this), checkPara);
            });
            obj.off('focus');
            obj.on('focus', function () {
                $(this).attr('data', this.value);
            });
            obj.off('blur');
            obj.on('blur', function () {
                var oldValue = $(this).attr('data');
                var nowValue = this.value;
                if (oldValue != nowValue) {
                    callback(this.value);
                }
            });
        },

        //表格数据上下移动处理
        chgTableDataUpDown: function (tblObj, isUp) {
            var selectedIndexes = tblObj.selectedRowsIndex();
            var index = selectedIndexes[0]; //只对被选中的第一条进行操作
            if (index == undefined) {
                return;
            }
            var pos = isUp ? -1 : 1;
            if ((isUp && index == 0) || //上移到第一条停止
                (!isUp && index == tblObj.rowsLength() - 1)) {//下移到最后一条停止
                tblObj.select(index);
                return;
            }
            //表格多选时的处理
            if (tblObj.opts.multiSelect) {
                tblObj.deselect('all');
                tblObj.select(index);       //选择要移动的行
                tblObj.select(index + pos);   //选择相邻的行
                var mItem = tblObj.selectedRows();
                if (isUp) {//上移时,数组反转一次
                    mItem.reverse();
                }
                tblObj.updateRow(mItem[0], index + pos);//移动行到目标行
                tblObj.updateRow(mItem[1], index);      //目标行到移动行

                tblObj.deselect('all');
                tblObj.select(index + pos);
            } else {
                var mItem = tblObj.selectedRows();
                tblObj.select(index + pos);
                var cItem = tblObj.selectedRows();

                tblObj.updateRow(mItem[0], index + pos);//移动行到目标行
                tblObj.updateRow(cItem[0], index);      //目标行到移动行
            }
        },
        //初始化下拉列表框的选项
        initSelectOptions: function (selObj, items, labelName, dataName, defVal, tipOption) {
            //清空所有选项
            selObj.empty();
            if (tipOption) {
                //如果需要提示选项
                selObj.append('<option value="">' + tipOption + '</option>');
            }
            $.each(items || [], function (i, item) {
                if (item) {
                    selObj.append('<option value="' + item[dataName ? dataName : 'data'] + '">'
                        + item[labelName ? labelName : 'label'] + '</option>');
                }
            });

            if (defVal) {
                selObj.val(defVal);
            }
        },
        getObjValue: function (target, name) {
            var value = "";
            if (target) {
                value = target.find('input[name="' + name + '"]').val();
            } else {
                value = $('input[name="' + name + '"]').val();
            }
            if (!value) {
                value = "";
            }
            return value;
        },
        getLabelFromList: function (arr, data, field) {
            var label = '';
            var self = this;
            $.each(arr || [], function (i, item) {
                if (item && item[field ? field : 'data'] == data) {
                    label = item.label;
                    return self.BREAK;
                }
            });
            return label;
        },

        getNodetypeDefinition: function (nodetype) {
            var result = null;
            var self = this;
            $.each(this.options.nodetype, function (key, item) {
                if (item && item.data == nodetype) {
                    result = item;
                    return self.BREAK;
                }
            });
            return result;
        },
        //打开一个窗口用来显示从服务器上获取的流程列表
        openWinForSelFlow: function (callback) {
            var self = this;
            this._getFlowListFromServer(function (data) {
                var flows = data && data.flows || [];
                var zNodes = self.initTreeData(flows);
                var html =
                    '<div style="background-color: #F5F5F5">' +
                    '<ul id="tree" class="ztree" style="width:300px;height:300px; overflow:auto;"></ul></div>' +
                    '<div style="display: block;position: absolute;margin-left: 305px;top: 0px">' +
                    '<select name="subflow" size=10 style="width:215px;height:300px;"></select>' +
                    '</div>';
                self.popSelWin(self.getLang('prop.selsubflow'), html,
                    function ($this) {
                        var flowid = $this.find('select[name="subflow"]').val();
                        if (!flowid) {
                            self.showMsg(self.getLang('prop.selsubflow'));
                            return false;
                        }
                        var label = $this.find('select[name="subflow"] :selected').text();
                        var flowname = label.substring(0, label.indexOf('('));
                        return callback(flowid, flowname);
                    },
                    '550px', null,
                    function ($this) {
                        //初始化树
                        $.fn.zTree.init($this.$content.find("#tree"), {
                            callback: {
                                onClick: function (event, treeId, treeNode) {
                                    initSelect(treeNode.data);
                                }
                            }
                        }, zNodes);
                        var initSelect = function (data) {
                            //初始化所有数据到列表中
                            var selSubflow = $this.$content.find('select[name="subflow"]');
                            selSubflow.empty();
                            $.each(data || [], function (i, item) {
                                if (item) {
                                    selSubflow.append('<option value="' + item.id + '">' + item.name + '(' + item.id + ')</option>');
                                }
                            });
                        };
                        initSelect(flows);
                    });

            });
        },

        //TODO 打开一个窗口用来显示事件列表
        openWinForSelEvent: function (callback) {
            var self = this;
            var showWin = function (data) {
                var data = data || [];
                var zNodes = self.initTreeData(data);
                var html =
                    '<div style="background-color: #F5F5F5">' +
                    '<ul id="tree" class="ztree" style="width:200px;height:300px; overflow:auto;"></ul></div>' +
                    '<div style="display: block;position: absolute;margin-left: 205px;top: 0px">' +
                    '<select name="eventlist" size=10 style="width:315px;height:300px;"></select>' +
                    '</div>';
                self.popSelWin(self.getLang('prop.selevent'), html,
                    function ($this) {
                        var eventid = $this.find('select[name="eventlist"]').val();
                        if (!eventid) {
                            self.showMsg(self.getLang('prop.selevent'));
                            return false;
                        }
                        var label = $this.find('select[name="eventlist"] :selected').text();
                        return callback(label, eventid);
                    },
                    '550px', null,
                    function ($this) {
                        //初始化树
                        $.fn.zTree.init($this.$content.find("#tree"), {
                            callback: {
                                onClick: function (event, treeId, treeNode) {
                                    initSelect(treeNode.data);
                                }
                            }
                        }, zNodes);
                        var initSelect = function (data) {
                            //初始化所有数据到列表中
                            var selEvent = $this.$content.find('select[name="eventlist"]');
                            selEvent.empty();
                            $.each(data || [], function (i, item) {
                                if (item) {
                                    selEvent.append('<option value="' + item.id + '">' + item.name + '</option>');
                                }
                            });
                        };

                        initSelect(data);
                    });
            };
            self._getEventListFromServer(showWin);
        },

        //流程跟踪历史记录表头生成
        historyTableHead: function () {
            var title = this.getLang('table.history.title');
            return [
                {
                    title: title[0],//'操作人',
                    name: 'username',
                    width: 90,
                    lockWidth: true,
                    align: 'left'
                },
                {
                    title: title[1],//'操作类型',
                    name: 'actionname',
                    width: 90,
                    lockWidth: true,
                    align: 'left'
                },
                {
                    title: title[2],//'操作节点',
                    name: 'nodename',
                    lockWidth: true,
                    width: 90,
                    align: 'left'
                },
                {
                    title: title[3],//' 操作时间',
                    name: 'actiontime',
                    width: 100,
                    lockWidth: true,
                    align: 'left'
                },
                {
                    title: title[4],//'累计时间',
                    name: 'dotime',
                    lockWidth: true,
                    width: 110,
                    align: 'left'
                },
                {
                    title: title[5],//'操作内容',
                    name: 'memo',
                    width: 260,
                    align: 'left'
                },
                {
                    title: title[6],//'意见',
                    name: 'comments',
                    width: 120,
                    align: 'left'
                }
            ];
        },
        //生成历史记录表
        makeHistoryTable: function ($this, items) {
            // var  items = self.data['history'] || [];
            var self = this;
            var tblObj = $this.$content.find('#popSel').mmGrid({
                height: 350
                , delTitle: self.getLang('table.field.defTitle')
                , showCol: self.getLang('table.field.showCol')
                , cols: self.historyTableHead()
                , items: items      //本地数据

                , multiSelect: false
                , fullWidthRows: true
                , autoLoad: false
                , loadingText: self.getLang('table.history.load') //'正在加载历史记录列表...'
                , noDataText: self.getLang('table.history.nodata')  //'当前无历史记录'
            });
            tblObj
                .on('cellSelected', function (e, item, rowIndex, colIndex) {

                })
                .load();

        },
        initFieldSelect: function (fieldSelect, formId, defVal) {
            //TODO 应该根据formId判断字段是否可以使用下拉框,还是输入框
            //下拉框时
            fieldSelect.empty();
            fieldSelect.append('<option value="">' + this.getLang('static.selfield') + '</option>');
            if (formId) {
                $.each(this.curDrawLayer.forms[formId]['fields'] || [], function (key, value) {
                    if (value && key.indexOf('mixed_') == 0) {
                        var field = value.split("&");
                        fieldSelect.append('<option value="' + key.split("mixed_")[1] + '" title="' + field[0] + '">' + field[1] + '</option>');
                    }
                });
            }
            if (defVal) {
                fieldSelect.val(defVal);
            }
        },

        //根据对象属性sort来排序
        sortObject: function (source, key, sort) {
            var tarArr = [];
            var sourceLenth = Object.keys(source).length;
            for (var i = 0; i < sourceLenth; i++) {
                tarArr[i] = null;
            }
            $.each(source, function (i, obj) {
                tarArr.splice(obj[sort], 1, obj);
            });
            var tarObj = {};
            $.each(tarArr, function (i, obj) {
                tarObj[obj[key]] = obj;
            });
            return tarObj;
        }
    };

    $.horizonFlowDesigner = flowdesigner;

    $.fn.horizonFlowDesigner = function (opts) {
        return flowdesigner.init(this, opts);
    };
    $.fn.horizonFlowDesigner.defaults = {
        /*
        imgBasePath:'', //图片资源路径
        serverUrl:'',   //从服务器端获取数据的路径
        suffix:'wf',
        eventlstUrl:'tmpdata/event.json',//事件列表数据获取地址
        //仅在showtype=3时有效
        //0=只获取一次(只要加载过,就不再从服务器上获取),1=每次仅获取实例数据,2=每次都获取所有数据
        loadSubFlag:1,
        waterOpacity:0.04,//水印的透明度
        subOpacity:[0.65,0.5],//子流程显示时,主流程图片的透明度,0=定义时显示的遮罩层透明度,1=流程监控时的主流程图的透明度
        screenScale:1,  //用于在屏幕分辨率比较大,操作系统默认放大显示的时候,用来调整图片坐标大小的(显示子流程节点的图片)
        resizeWidth:false,   //是否根据节点坐标调整画布大小(流程跟踪,流程监控时)
        resizeHeight:false,   //是否根据节点坐标调整画布大小(流程跟踪,流程监控时)
        part: {
            image:{
                width:30,
                height:30
            },
            defaultType: {
                Start: '0',
                Node: '10',
                Event: '81',
                Gateway: '72',
                Robot: '41',
                Virtual:'900',
                Cluster: '210',
                Subflow:'60',
                End: '100'
            }
        },
        fileMenuPos:[12,-6],//文件菜单位置
        //节点类型信息,不要随意修改
        nodeNameWidth:50,//节点名称运行显示的宽度
        nodetype: {
            Node_Start: {
                id:'Node_Start',
                data: 0,
                label: '人工开始',
                title: '由用户手动发起流程',
                className: 'com.horizon.wf.expand.node.NodeStartImpl'
            },
            Node_Timer_Start: {
                id:'Node_Timer_Start',
                data: 1,
                label: '定时开始',
                title: '由定时任务在后台发起',
                className: 'com.horizon.wf.expand.node.NodeStartImpl'
            },
            Node_Signal_Start: {
                id:'Node_Signal_Start',
                data: 2,
                label: '信号开始',
                title: '当前捕获到指定信号时由后台发起',
                className: 'com.horizon.wf.expand.node.NodeStartImpl'
            },
            Node_Msg_Start: {
                id:'Node_Msg_Start',
                data: 3,
                label: '消息开始',
                title: '当接收到指定消息时由后台发起',
                className: 'com.horizon.wf.expand.node.NodeStartImpl'
            },

            Node_Single: {
                id:'Node_Single',
                data: 10,
                label: '单人节点',
                title: '办理人只能指定一个',
                className: 'com.horizon.wf.expand.node.NodeSingleImpl'
            },
            Node_Multi_Single: {
                id:'Node_Multi_Single',
                data: 11,
                label: '多人单一',
                title:'办理人可以指定多个,但只允许一个人办理',//抢单

                className: 'com.horizon.wf.expand.node.NodeMultiSingleImpl'
            },
            Node_Multi: {
                id:'Node_Multi',
                data: 20,
                label: '多人并行',
                title:'办理人可以指定多个,按照下面的规则进行办理',//异步,独占
                className: 'com.horizon.wf.expand.node.NodeMultiImpl'
            },
            Node_Order: {
                id:'Node_Order',
                data: 25,
                label: '多人顺序',
                title:'办理人可以指定多个,按照顺序逐个进行办理',
                className: 'com.horizon.wf.expand.node.NodeOrderImpl'
            },
            Node_Merger: {
                id:'Node_Merger',
                data: 30,
                label: '人工合并',
                title:'只能有一个办理人',//合并所有分支
                className: 'com.horizon.wf.expand.node.NodeMergerImpl'
            },
            Node_Progressively: {
                id:'Node_Progressively',
                data: 50,
                label: '内部循环',
                title:'在节点内部继续流转(逐级审批)',
                className: 'com.horizon.wf.expand.node.NodeProgressivelyImpl'
            },

            // Node_Auto : 40,			//自动节点
            Node_Auto_Program: {
                id:'Node_Auto_Program',
                data: 41,
                label: '自动程序',
                title:'由定时任务触发',
                className: 'com.horizon.wf.expand.node.NodeAutoImpl'
            },
            // Node_Auto_Rule : 42,//自动业务规则
            // Node_Auto_Service : 43,//自动服务任务

            Node_Sub: {
                id:'Node_Sub',
                data: 60,
                label: '子流程',
                title:'自动创建配置的子流程实例',
                className: 'com.horizon.wf.expand.node.NodeSubFlowImpl'
            },

            // Node_Gateway : 70,	//网关
            Node_GateWay_Split: {
                id:'Node_GateWay_Split',
                data: 71,
                label: '分支网关',
                title:'分支',
                className: 'com.horizon.wf.expand.node.NodeConditionImpl'
            },
            Node_GateWay_Merge: {
                id:'Node_GateWay_Merge',
                data: 72,
                label: '合并网关',
                title:'无人参与',
                className: 'com.horizon.wf.expand.node.GateWayMergeImpl'
            },

            // Node_AutoUnit : 73,

            // Node_Event: 80,
            Node_Event_Intermediate: {
                id:'Node_Event_Intermediate',
                data: 81,
                label: '中间事件',
                title:'由定时任务触发,立即执行',
                className: 'com.horizon.wf.expand.node.NodeAutoImpl'
            },
            Node_Event_Timer: {
                id:'Node_Event_Timer',
                data: 82,
                label: '定时事件',
                title:'由定时任务触发,按设置时间',
                className: 'com.horizon.wf.expand.node.NodeAutoImpl'
            },
            Node_Event_Message: {
                id:'Node_Event_Message',
                data: 83,
                label: '消息事件',
                title:'由定时任务触发,接收到指定消息后',
                className: 'com.horizon.wf.expand.node.NodeAutoImpl'
            },
            Node_Event_Signal_Throw: {
                id:'Node_Event_Signal_Throw',
                data: 84,
                label: '信号抛出',
                title:'由定时任务触发,按设置抛出信息后',
                className: 'com.horizon.wf.expand.node.NodeAutoImpl'
            },
            Node_Event_Signal_Catch: {
                id:'Node_Event_Signal_Catch',
                data: 85,
                label: '信号捕获',
                title:'由定时任务触发,当前捕获到指定信息后',
                className: 'com.horizon.wf.expand.node.NodeAutoImpl'
            },

            // Node_Flow_Fragment : 91,	//流程片段

            Node_End: {
                id:'Node_End',
                data: 100,
                label: '分支结束',
                title:'当前分支结束(如果只有一个分支,则实例流转结束)',
                className: 'com.horizon.wf.expand.node.NodeEndImpl'
            },
            Node_End_Instance: {
                id:'Node_End_Instance',
                data: 101,
                label: '实例结束',
                title:'如果有其他分支,则取消其他分支,实例流转结束',
                className: 'com.horizon.wf.expand.node.NodeEndImpl'
            },

            Node_Mutual: {
                id:'Node_Mutual',
                data: 210,
                label: '引擎交互',
                title:'多引擎协作流转时,用来转换引擎服务器',
                className: ''
            },

            Node_Virtual: {id:'Node_Virtual',data: 900, label: '虚拟节点', className: ''}
        },
        //流程跟踪图显示时使用的参数
        flownode: {
            image: {
                width: 50,
                height: 50,
                defurl:     '/img/define/node_',
                doneurl:    '/img/done/node_',
                jumpurl:    '/img/jump/node_',
                waringurl:  '/img/extended/node_',
                nowurl:     '/img/now/node_',
                deleteurl:  '/img/delete.png'
            },
            color:{
                extended: '#DF3031',
                jump: '#1F76C8',
                done: '#529208',
                now: '#FF8600',
                define: '#868686'
            },
            colorTip:{
                extended:'超期节点',
                jump:'跳过节点',
                done:'已办理节点',
                now:'活动节点',
                define:'未办理节点'
            }
        },
        //流程跟踪状态显示区域位置
        iconPosition:{
            isH:true,       //是否横排
            x:'left',           //left,right,number
            xpos:0,
            y:'bottom',      //bottom,top,number
            ypos:0,
            ymin:460,       //y的最小值避免太靠上
            opacity:0.6     //标示虚化
        },
        limitTypes:[
            {label:'自然日',data:'1'},
            {label:'工作日',data:'0'}
            // {label:'小时',data:'2'},
            // {label:'分钟',data:'3'}
        ],
        varTypes: [
            {label: '字符', data: '1'},
            {label: '数字', data: '2'},
            {label: '布尔值', data: '3'},
            {label: '日期',data: '4'},
            {label: '日期时间', data: '5'},
            {label: '组织机构', data: '6'},
            {label: '其他', data: '10'}
        ],
        orgTypes:{
            person:'用户',
            dept:'部门',
            depts:'部门(不含)',
            group:'群组',
            position:'岗位'
        },
        deptTypes:{
            D:'含子部门',
            S:'不含子部门',
            DJ:'接口人',
            DF:'负责人',
            DL:'分管领导'
        },
        control:{
            OuterSelect:{
                label:'由外部设置办理人'
            },
            ManualSelect: {
                label: '需要从设置列表中选择办理人'
            },
            FreeSelect: {
                label: '办理人为空时，允许选择',
                title: '选择时的范围，可以自定义。\n都不选时表示允许所有等同全选',
                select:true,
                area:[
                    {label:'部门',data:'D'},
                    {label:'群组',data:'G'},
                    {label:'岗位',data:'P'}
                ]
            },
            AutoPass: {
                label: '办理人为空时，跳过此节点',
                title:'开始节点提交到此节点时，此设置无效\n（创建新实例时，第一个节点不允许跳过）'
            },
            PassCurUser: {
                label: '办理人包含当前人时，跳过此人'
            },
            PassNodeUser: {
                label: '跳过指定节点办理人',
                passNode:true
            },
            AgentFlag: {
                label: '代办设置生效'
            },
            OnlySelectUser: {
                label: '仅允许选择人员'
            },
            Author:['OuterSelect','ManualSelect','FreeSelect','AutoPass','PassCurUser','PassNodeUser','AgentFlag','OnlySelectUser'],
            SecondAuthor:['ManualSelect','FreeSelect','OnlySelectUser'],
            Reader:['OuterSelect','ManualSelect','FreeSelect','OnlySelectUser']
        },
        exceptions:{
            WFE_0001:'实例创建事件异常',
            WFE_0010:'节点超期',
            WFE_0020:'事件接口执行失败',
            WFE_0030:'事件节点自动提交失败',
            WFE_0040:'网关接口执行失败',

            WFE_0060:'节点进入事件执行失败',
            WFE_0070:'节点离开事件执行失败',
            WFE_0080:'当前节点实例打开事件执行失败',
            WFE_0090:'节点操作完成事件执行失败',
            WFE_0120:'节点进入规则运算异常',
            WFE_0140:'节点自动激活执行失败',

            WFE_0160:'节点结束规则运算异常',
            WFE_0200:'自动节点程序执行异常',
            WFE_0210:'自动节点业务规则执行异常',
            WFE_0220:'自动节点服务执行异常',
            WFE_0230:'全局超期'
        },
        dealType: [
            {label: '忽略', data: '1'},
            {label: '跳转', data: '2'},
            {label: '挂起', data: '3'},
            {label: '终止', data: '4'},
            {label: '自定义', data: '0'}
        ],
        sendMsg:{
            Read:'待阅',
            Mail:'邮件',
            Msg:'系统消息',
            SMS:'短信',
            IM:'即时消息'
        },
        eventType: {
            flowopen: '打开节点时执行',
            flowin: '进入节点执行',
            flowout: '离开节点执行',
            flowsave: '操作完成前执行'
        },

        //操作默认选中
        defOperator:{
            Author: ['submit', 'startflow', 'save'],
            SecondAuthor: ['secondSubmit', 'save'],
            Reader: ['addreader', 'readed'],
            Done: ['getback'],
            Creator: ['urge','startflow'],
            Manager: ['replace', 'stop', 'pause', 'goto', 'reduceAuthor']
        },
        subflow:'subflow',//启动子流程按钮的id,必须跟operators里面定义的要一致
        operators: {
            Author: ['startflow','submit','save','addSecondauthor','innerSubmit','freesubmit',
                     'reject', 'jumpreject', 'innerreject','rejectSubmit','addreader',
                     'huiqian','huiqianSubmit','jiaqian','jiaqianBefore','reduceAuthor',
                     'goto','stop',  'pause', 'move',
                     'subflow'],
            SecondAuthor: ['secondSubmit', 'addSecondauthor', 'save'],
            Reader: ['addreader', 'readed'],
            Done: ['getback', 'reduceAuthor', 'reissue', 'reissuerouter'],
            Creator: ['urge', 'cancel', 'startflow'],
            Manager: ['replace', 'stop', 'pause', 'goto', 'reduceAuthor'],

            startflow: {
                name: '启动流程', id: 'startflow',
                implClass: 'com.horizon.wf.action.ActionSubmitFirst',
                node: 'start',
                reName: '启动流程',
                memo: '启动流程'
            },
            submit: {
                name: '提交', id: 'submit',
                implClass: 'com.horizon.wf.action.ActionSubmit',
                node: 'task',
                reName: '提交',
                memo: '正常状态下的提交'
            },
            secondSubmit: {
                name: '协办提交', id: 'secondSubmit',
                implClass: 'com.horizon.wf.action.ActionSubmitNotLeave',
                node: 'task',
                reName: '协办提交',
                memo: '协办状态下的提交'
            },
            innerSubmit: {
                name: '内部提交', id: 'innerSubmit',
                implClass: 'com.horizon.wf.action.ActionSubmitForProgressively',
                //中括号中的数字表示例外节点类型,圆括号中的数字表示仅适应的节点类型
                node: 'task~(50)',//仅内部循环
                reName: '内部提交',
                memo: '不离开节点内部循环时提交'
            },
            freesubmit: {
                name: '自由提交', id: 'freesubmit',
                implClass: 'com.horizon.wf.action.ActionSubmitForFree',
                node: 'task~[30]',//合并除外
                reName: '自由提交',
                memo: '在没有定义下一节点的情况下执行提交,系统自动创建一个节点'
            },
            huiqianSubmit: {
                name: '会签提交', id: 'huiqianSubmit',
                implClass: 'com.horizon.wf.action.ActionSubmitHuiqian',
                node: 'task~[30][50]',//合并和内部循环除外
                reName: '会签提交',
                memo: '会签状态下的提交'
            },
            rejectSubmit: {
                name: '退回提交', id: 'rejectSubmit',
                implClass: 'com.horizon.wf.action.ActionSubmitForReject',
                node: 'task',
                reName: '退回提交',
                memo: '退回状态下的提交'
            },
            huiqian: {
                name: '会签', id: 'huiqian',
                implClass: 'com.horizon.wf.action.ActionHuiQian',
                node: 'task~[30][50]',//合并和内部循环除外
                reName: '发起会签',
                memo: '发起会签'
            },
            jiaqianBefore: {
                name: '前加签', id: 'jiaqianBefore',
                implClass: 'com.horizon.wf.action.ActionJiaQianBefore',
                node: 'task~(25)',//仅多人顺签
                reName: '前加签',
                memo: '前加签'
            },
            reduceAuthor: {
                name: '减签', id: 'reduceAuthor',
                implClass: 'com.horizon.wf.action.ActionReduceAuthor',
                node: 'task~(20)(25)',//仅多人节点(多人并行,多人顺序)
                reName: '减签',
                memo: '减少办理人'
            },
            jiaqian: {
                name: '加签', id: 'jiaqian',
                implClass: 'com.horizon.wf.action.ActionJiaQian',
                node: 'task~(20)(25)',//仅多人节点(多人并行,多人顺序)
                reName: '加签',
                memo: '添加办理人'
            },
            reject: {
                name: '退回', id: 'reject',
                implClass: 'com.horizon.wf.action.ActionReject',
                node: 'task',
                reName: '退回',
                memo: '退回到之前的办理节点'
            },
            jumpreject: {
                name: '任意退回', id: 'jumpreject',
                implClass: 'com.horizon.wf.action.ActionRejectByJump',
                node: 'task',
                reName: '任意退回',
                memo: '任意退回到之前的办理节点'
            },
            innerreject: {
                name: '内部退回', id: 'innerreject',
                implClass: 'com.horizon.wf.action.ActionRejectForInner',
                node: 'task~(25)(50)',//仅多人顺序和内部循环
                reName: '内部退回',
                memo: '节点内部退回'
            },
            reissue: {
                name: '补发', id: 'reissue',
                implClass: 'com.horizon.wf.action.ActionReissue',
                node: 'task~(20)(25)',//仅多人顺序和内部循环
                reName: '补发',
                memo: '办理人补发'
            },
            reissuerouter: {
                name: '分支补发', id: 'reissuerouter',
                implClass: 'com.horizon.wf.action.ActionReissueRouter',
                node: 'task~[30]',//合并除外
                reName: '分支补发',
                memo: '分支补发'
            },
            getback: {
                name: '拿回', id: 'getback',
                implClass: 'com.horizon.wf.action.ActionGetBack',
                node: 'task',
                reName: '拿回',
                memo: '从当前办理节点拿回'
            },
            save: {
                name: '暂存', id: 'save',
                implClass: 'com.horizon.wf.action.ActionSave',
                node: 'task',
                reName: '暂存',
                memo: '保存表单数据'
            },
            goto: {
                name: '跳转', id: 'goto',
                implClass: 'com.horizon.wf.action.ActionGoto',
                node: 'task,end,subflow',
                reName: '跳转',
                memo: '跳转到其他办理节点'
            },
            move: {
                name: '转办', id: 'move',
                implClass: 'com.horizon.wf.action.ActionMove',
                node: 'task',
                reName: '转办',
                memo: '送其他人办理'
            },
            cancel: {
                name: '撤办', id: 'cancel',
                implClass: 'com.horizon.wf.action.ActionCancel',
                node: 'task;event;robot;gateway;cluster',
                reName: '撤办',
                memo: '撤销办理'
            },
            pause: {
                name: '暂停', id: 'pause',
                implClass: 'com.horizon.wf.action.ActionPause',
                node: 'task;event;robot;gateway;cluster',
                reName: '暂停',
                memo: '流程暂停流转'
            },
            replace: {
                name: '替换处理人', id: 'replace',
                implClass: 'com.horizon.wf.action.ActionReplaceAuthor',
                node: 'task',
                reName: '替换处理人',
                memo: '替换当前节点的办理人'
            },
            stop: {
                name: '终止', id: 'stop',
                implClass: 'com.horizon.wf.action.ActionStop',
                node: 'task;event;robot;gateway;cluster',
                reName: '终止',
                memo: '流程终止'
            },
            addSecondauthor: {
                name: '增加协办', id: 'addSecondauthor',
                implClass: 'com.horizon.wf.action.ActionAddSecondAuthor',
                node: 'task',
                reName: '增加协办',
                memo: '主办需要指定协办时的操作'
            },
            addreader: {
                name: '阅知', id: 'addreader',

                implClass: 'com.horizon.wf.action.ActionAddReader',
                node: 'task;event;gateway;robot;end;cluster;subflow',
                reName: '发送阅知',
                memo: '发送阅知'
            },
            readed: {
                name: '已阅', id: 'readed',
                implClass: 'com.horizon.wf.action.ActionReaded',
                node: 'task;event;robot;end;gateway;cluster;subflow',
                reName: '已阅',
                memo: '标识待阅文件已阅'
            },
            urge: {
                name: '催办', id: 'urge',
                implClass: 'com.horizon.wf.action.ActionReMsg',
                node: 'task',
                reName: '催办',
                memo: '发起催办'
            },
            subflow: {
                name: '启动子流程', id: 'subflow',
                implClass: 'com.horizon.wf.action.ActionStartMultiSubFlow',
                node: 'task',
                reName: '启动子流程',
                memo: '发起一个子流程实例'
            }
        },
        participantsName:{
            Author:'主办',
            SecondAuthor:'协办',
            Reader:'读者',
            Done:'已办',
            Creator:'创建者',
            Manager:'管理员'
        },
        sendUser:[{label:'流程启动者',data:'1'},{label:'流程管理员',data:'2'}],
        relations:[
            {data:'1',label:'同部门人员'},
            {data:'2',label:'直接部门领导'},
            {data:'3',label:'所有上级领导'},
            {data:'4',label:'直接下属'},
            {data:'5',label:'所有下属'},
            {data:'6',label:'上级主管领导'},
            {data:'9',label:'上一级部门所有人员(含子部门)'},
            {data:'16',label:'上一级部门所有人员(不含子部门)'},
            {data:'15',label:'部门接口人'},
            {data:'17',label:'上级岗位'},
            {data:'18',label:'上级岗位人员'},
            {data:'19',label:'下级岗位'},
            {data:'20',label:'下级岗位人员'},
            {data:'99',label:'返回基准人'}
        ],

        operatorListCon:[{label:"包含",data:"in"},{label:"不包含",data:"noIn"}],
        operatorListStr:[{label:"等于",data:"=="},{label:"不等于",data:"!="}],
        operatorListNum:[{label:"大于",data:">"},{label:"大于等于",data:">="},
            {label:"小于",data:"<"},{label:"小于等于",data:"<="},
            {label:"等于",data:"=="},{label:"不等于",data:"!="}],

        relationNodeOption:{d_0:'无',d_1:'上一节点',d_2:'指定节点'},
        relationBaseOption: {d_0:'无',d_1:'办理人',d_2:'流程启动者',d_3:'当前执行人'},
        relationOption : {d_Creator:'流程启动者',d_PreDone:'上一节点办理',d_CurUser:'当前执行人'},

        ruleEditorPage:'/hz7sp2/workflow/module/rule/rule.editor.index.html',
        testFlowPage:'/hz7sp2/workflow/module/workflow/index.html',
        language: {  "static": {    "newFlow": "新流程",    "ok": "确认",    "cancel": "取消",    "close": "关闭",    "clearRule": "清除",    "warning": "警告",    "info": "提示",    "local": "保存到本地",    "server": "保存到服务器",    "saveinfo": "保存到本地还是服务器?",    "savenew": "保存到服务器时,存为新版本.<br>(仅流程定义保存,且状态为非发布时)",    "align":"对齐方式",    "aligninfo":"至少要选择两个以上的节点才可以执行对齐.",    "alignleft":"左对齐,以选择节点最左边的节点为准",    "alignright":"右对齐,以选择节点最右边的节点为准",    "alignup":"上对齐,以选择节点最上边的节点为准",    "aligndown":"下对齐,以选择节点最下边的节点为准",    "nocopy": "修改实例时不可复制",    "opensub": "打开过子流程的情况下不允许复制",    "clear":"画布上的所有节点和路由都将被删除,是否确认清空?",    "save": "保存",    "saveok": "保存成功!",    "saveError": "保存失败!",    "savemsg": "请先打开流程属性编辑界面并修改默认的流程ID",    "nodesnull": "没有任何节点时,不允许保存!",    "nodealone": "以下节点没有路由:",    "copyover": "应用到其他节点执行完毕!",    "swimlanes":"泳道",    "swimlanesdirector":"泳道方向:",    "swimlanesnum":"泳道数目:",    "swimlanesh":"水平",    "swimlanesv":"竖直",    "delswimlanes":"确认要删除所有泳道吗",    "delswimlane": "确认要删除[ name ]泳道吗?",    "inputswimname": "请输入新的标题:<br/>",    "selposerr": "下一节点的位置应该在合理的空白处选择.",    "delnode": "确认要删除[ name ]节点吗?<br>注意:跟此节点相关的路由也将全部被删除.",    "nodehistory": "节点[ name ]历史记录",    "allhistory": "历史记录",    "nohistory": "当前节点没有流转记录",    "test": "流程状态为[ 在修改 ]时不允许测试流程",    "nosave": "当前流程为新建未保存,请先保存流程.",    "startRoute": "当前节点只能作为路由的开始点,而不能作为结束点.",    "startOnly": "当前节点只允许有一条出口路由.当前节点已有出口路由.",    "endRoute": "结束节点只能作为路由的结束点,而不能作为开始点.",    "startToEnd": "开始节点不能直接指向结束节点.",    "delrouter": "确认要删除[ name ]路由吗?",    "routeInit": "折线路由[ name ]恢复时计算点出现不匹配,忽略输入信息,以自动计算为准.",    "dataerror": "数据格式不对.",    "loaderror": "数据加载失败!",    "testerror": "自动测试执行失败!",    "mainisnull":"运行故障,主流程对象丢失.",    "logImgName": "截图",    "copyInput": "请输入新的流程id:",    "testflowid": "测试的流程ID:",  "testflowNextStep": "是否自动下一步",  "testuserid": "启动人员ID:",    "onlyver": "当前流程只有一个版本",    "showver": "版本: ",    "instances": "节点[ name ] 实例列表",    "selnode": "请选择节点",    "selver": "请选择一个版本",    "selfield": "请选择字段",    "seluser": "请选择办理人",    "selsubflow": "请选择一个子流程",    "delcksel": "请先选择要删除的数据",    "mergerMsg1": "激活规则为【立即激活】或者【所有分支到达后激活】时，不允许勾选此选项。",    "mergerMsg2": "离开规则选择【等到所有分支】时，不允许勾选此选项。",    "mergerMsg3": "激活分支数小于离开规则分支数时，不允许勾选此选项。",    "mergerMsg4": "合并激活规则中的选项需要指定节点",    "mergerMsg5": "合并离开规则中的选项需要指定节点",    "addsub": "当前节点设置了子流程,但是没有选择[ name ]操作!<br>系统默认已勾选[ name ]！",    "delsub": "当前节点选择了[ name ]操作,但是没有指定子流程!<br>系统默认已取消[ name ]!",    "nogroup": "未分类"  },  "prop": {    "title": "name [ id ] 属性",    "apply": "应用",    "add": "添加",    "custome": "自定义",    "fieldset": "[ name ]字段权限设置",    "seltype": "请选择流程分类",    "selmainform": "请选择一个表单作为主表单",    "selsubflow": "请选择流程",    "selform": "请指定表单",    "selfield": "请指定字段",    "selvar": "请选择变量",    "selnode": "请指定节点:",    "selevent": "请选择事件",    "chgflowid": "请修改流程ID为非默认值。",    "flowidnull": "流程ID不能为空。",    "flowexist": "已经存在，请重新输入。",    "inodename": "请输入节点名称",    "nodeseltype": "'请选择后续分支类型",    "ntypenull": "节点类型为空",    "nclassnull": "节点实现类必须要指定",    "jumpuser": "跳过指定节点办理人时,需要指定节点",    "scopeset": "范围设置",    "conditionset": "路由条件",    "inputcon": "请输入判断内容",    "dateErr1": "输入的日期格式不正确(参考:2019-06-14)",    "dateErr2": "输入的日期格式不正确(参考:2019-06-14 10:52:00)",    "nodechg": "节点属性已修改,是否保存修改?",    "msgflag": "消息发送方式:",    "propset": "相关属性设置:",    "relation":{      "user": "办理人",      "creator": "流程启动者",      "preuser": "上一节点办理人",      "curuser": "当前执行人"    },    "selall": ["节点全选","表单全选"],    "tooltip": "多选时按住Ctrl点击可以选中和取消",    "selnode_user": "请选择节点(有办理人的节点)",    "subexist": "所选流程已在列表中"  },  "table": {    "form": {      "load": "正在加载表单列表...",      "nodata": "请添加流程需要的表单",      "selform": "请选择表单",      "selrplform": "请从列表中选择要替换的表单",      "trckform": "流程跟踪是内置表单不可替换",      "trackname": "流程跟踪",      "del": "确认要删除选中的表单吗?",      "delAll": "确认要删除所有的表单吗?",      "title": ["名称","ID","类型","版本","分组"]    },    "var": {      "load": "正在加载流程变量列表...",      "nodata": "请添加流程变量",      "idnull": "变量ID不能为空",      "chgidexist": "修改后的变量ID已经存在",      "idexist": "变量ID已经存在",      "del": "确认要删除选中的变量吗?",      "delAll": "确认要删除所有的变量吗?",      "title": ["ID","名称","类型","长度","初始值","数据来源","说明"]    },    "org": {      "load": "正在加载组织人员列表...",      "nodata": "请添加组织人员",      "del": "确认要删除选中的组织吗?",      "delAll": "确认要删除所有的组织吗?",      "title": ["组织名称","组织ID","类型","含子部门","不含子部门"]    },    "monitor": {      "load": "正在加载实例列表...",      "nodata": "当前无记录",      "noinstance": "没有从后台获取到对应的实例数据.",      "title": ["标题"]    },    "event": {      "load": "正在加载节点事件列表...",      "nodata": "请添加节点事件",      "namenull": "事件名称不能为空",      "classnull": "事件执行类不能为空",      "seltype": "请选择事件执行类型",      "chgtypeExist": "修改后的事件类型已经存在,每种类型只能添加一次",      "typeExist": "事件类型已经存在",      "del": "确认要删除选中的事件吗?",      "delAll": "确认要删除所有的事件吗?",      "title": ["事件名称","事件处理类","事件类型"]    },    "field":{      "load": "正在加载字段列表...",      "nodata": "请添加字段",      "chgexist": "修改后的字段已经存在",      "exist": "字段已经存在",      "del": "确认要删除选中的字段吗?",      "delAll": "确认要删除所有的字段吗?",      "title": ["表单_字段"]    },    "uservar": {      "load": "正在加载变量列表...",      "nodata": "当前无可选变量",      "title": ["选择","变量ID","变量名称","变量类型"]    },    "relation": {      "load": "正在加载相对关系列表...",      "nodata": "请添加相对关系",      "exist": "关系已经存在,请勿重复添加.",      "del": "确认要删除选中的关系吗?",      "delAll": "确认要删除所有的关系吗?",      "title": ["相对节点","相对基准","相对关系"]    },    "subflow": {      "load": "正在加载子流程列表...",      "nodata": "请添加子流程",      "sel": "不允许启动多个子流程时,不能选择多个子流程",      "set": "流程变量传递设置中存在[接受自][双向]时不能取消此设置",      "del": "确认要删除选中的子流程吗?",      "delAll": "确认要删除所有的子流程吗?",      "title": ["子流程名称","子流程ID"]    },    "subvar": {      "load": "正在加载变量列表...",      "nodata": "请添加主子流程变量交互方式",      "del": "确认要删除选中的流程变量传递设置吗?",      "delAll": "确认要删除所有的流程变量传递设置吗?",      "flag": "请选择传输方式",      "exist": "修改后的主流程变量和子流程变量已经存在列表中",      "type": {        "IN":"输出至",        "OUT":"接受自",        "INOUT":"双向"      },      "title": ["主流程变量名称","主流程变量ID","输入/输出","子流程变量名称","子流程变量ID"]    },    "exception": {      "load": "正在加载异常列表...",      "nodata": "请添加异常处理方式",      "sel": "请选择异常名称",      "iname": "请输入自定义的异常名称",      "icode": "请输入自定义的异常代码",      "dealflag": "请输入自定义的处理方式",      "jumpnode": "请选择要跳转到的节点",      "chgexist": "修改后的异常已经存在,每种类型只能添加一次",      "exist": "异常已经存在",      "del": "确认要删除选中的异常吗?",      "delAll": "确认要删除所有的异常吗?",      "title": ["异常名称","异常代码","异常消息","通知对象","异常处理"]    },    "para": {      "load": "正在加载节点参数列表...",      "nodata": "请添加节点参数",      "idnull": "参数ID不能为空",      "namenull": "参数名称不能为空",      "chgexist": "修改后的参数ID已经存在",      "exist": "参数ID已经存在",      "del": "确认要删除选中的参数吗?",      "delAll": "确认要删除所有的参数吗?",      "title": ["参数ID","参数名称","默认值"]    },    "action": {      "load": "正在加载操作列表...",      "nodata": "当前无可选操作",      "selnode": "请选择节点(多选)",      "msg": "id: ID <br>实现类：CLASS <br>说明:MEMO",      "title": ["选择","名称","别名","实现类","详情","查看"]    },    "nform": {      "load": "正在加载表单列表...",      "nodata": "当前无可选表单",      "loaderr": "表单数据获取异常",      "selbtn": "请选择表单操作",      "title": ["选择","表单名称","已选操作","分组","字段权限","应用","全编辑","全只读","新建","编辑"]    },    "nfield": {      "load": "正在加载字段列表...",      "nodata": "当前无可选字段",      "def": "未标示",      "iname": "请输入字段权限设置名称",      "title": ["标示","字段名称","编辑","必填","只读","隐藏"]    },    "selnode": {      "load": "正在加载节点列表...",      "nodata": "当前无可选节点",      "title": ["选择","节点(ID)","选中此表单"]    },    "history": {      "load": "正在加载历史记录列表...",      "nodata": "当前无历史记录",      "title": ["操作人","操作类型","操作节点","操作时间","累计时间","操作内容","意见"]    },    "condition": {      "load": "正在加载路由条件列表...",      "nodata": "当前没有路由条件或者为xml格式转换后的数据，请点击【切换】查看",      "del": "确认要删除选中的路由条件吗?",      "delAll": "确认要删除所有的路由条件吗?",      "insert": "请选择要插入的位置",      "edit": "请选择要修改的路由条件",      "editinsert": "某条数据正在修改中",      "title": ["关系","左括号","变量名称","对比","值","右括号","插入","删除","全删","切换"]    }  },  "menu": {    "flowpro": "属性设置",    "savelocal": "保存到本地",    "saveserver": "保存到服务器",    "openlocal": "从本地打开",    "copy": "复制此流程",    "addswim": "添加泳道",    "left": "左对齐",    "right": "右对齐",    "top": "上对齐",    "bottom": "下对齐",    "drag": "允许拖动/禁止选择",    "select": "禁止拖动/允许选择",    "original": "原大小",    "zero": "回到原点",    "start": "初始位置大小",    "dynamic": "动态演示",    "saveimg": "截图",    "mousewheel": "启用滚轮缩放,禁用滚轮缩放",    "history": "历史记录",    "back": "返回流程",    "restart":"重新开始",    "showdata": "数据查看",    "refresh": "刷新页面",    "hisver": "历史版本",    "testflow": "测试流程",    "autotest": "自动测试",    "testend": "已经结束.",    "routerpro": "路由属性",    "delrouter": "删除路由",    "alone": "未显示节点",    "chgswim": "修改标题",    "delallswim": "删除所有泳道",    "chgswimname": "修改泳道名称",    "delswim": "删除此泳道",    "nodebase": "基本属性",    "nodeuser": "办理人设置",    "nodeoperator": "操作权限",    "nodeEvent": "事件",    "nodesubflow": "子流程",    "nodeExtend": "扩展规则",    "nodeException": "异常处理",    "nodepara": "节点参数",    "nodecluster": "交互设置",    "delnode": "删除此节点",    "copynode": "复制当前节点",    "import": "从模版导入",    "savemodule": "存为模版",    "showsubflow": "显示子流程"  },  "parts": {    "Start": "开始",    "Node": "任务",    "Event": "事件",    "Gateway": "网关",    "Robot": "自动",    "Cluster": "交互",    "Subflow": "子流程",    "Virtual": "虚拟",    "End": "结束",    "swimlanes": "泳道",    "line": "直线",    "brokenline": "折线",    "route": "路由",    "clear":"清空",    "select":"选择",    "align":"对齐",    "new": "新建",    "openserver": "从服务器打开",    "openlocal": "从本地打开",    "savelocal": "保存到本地",    "saveserver": "保存到服务器",    "savenewver": "保存新版本到服务器",    "copy":"复制当前流程",    "nodemodule": "节点模版列表",    "group": "群组"  }}
        //*/
    };

    return flowdesigner;
});

define('flowdesigner', ['flowdesigner/flowdesigner'], function (main) { return main; });
