jQuery工作流插件之gooflow流程解决方案

jQuery工作流插件之gooflow流程解决方案

特点

1、跨浏览器,可兼容IE7--IE11, FireFox, Chrome, Opera等几大内核的浏览器,且不需要浏览器再加装任何控件。 (IE7-IE8时,使用VML;IE9以上,FF,OPERA,CHROME,SAFARI上使用SVG) 
2、 多系统兼容性、可移植性:由于只包括前台UI,因此二次开发者可很方便将本插件用在任何一种需要流程图的B/S系统应用上,流程图的详细实现逻辑完全交于后台程序开发者自己实现;对于后台,只要能返回/接收能被本插件解析的JSON格式数据即可.所以本插件可用于不同的服务器语言建立的后台上. 
3、跨领域:流程图设计器不止用在电信领域,在其它需要IT进行技术支持的领域中都有重大作用. 

以下从纯技术实现层面具体描述: 
1、 页面顶部栏、左边侧边栏均可自定义; 
2、当左边的侧边栏设为不显示时,为只读状态,此时的视图区可当作是一个查看器而非编辑器。 
3、侧边工具栏除了基本和一些流程节点按钮外,还自定义新的节点按钮,自定义节点都可以有自有的图标、类型名称,定义后在使用可可在工作区内增加这些自定义节点。 
4、顶部栏可显示流程图数据组的标题,也可提供一些常用操作按钮。 
5、 顶部栏的按钮,除了撤销、重做按钮外,其余按钮均可自定义点击事件。 
6、 可画直线、折线;折线还可以左右/上下移动其中段。 
7、 具有区域划分功能,能让用户更直观地了解哪些节点及其相互间的转换,是属于何种自定义区域内的。 
8、 具有标注功能,用橙红色标注某个结点或者转换线,一般用在展示流程进度时。 
9、 能直接双击结点、连线、分组区域中的文字进行编辑 
10、 在对结点、连线、分组区域的各种编辑操作,如新增/删除/修改名称/重设样式或大小/移动/标注时,均可捕捉到事件,并触发自定义事件,如果自定义事件执行的方法返回FALSE,则会阻止操作。 
11、 具有操作事务序列控制功能,在工作区内的各种有效操作都能记录到一个栈中,然后可以进行撤销(undo())或重做(redo()),像典型的C/S软件一样。 

界面风格

在线案例一、gooflow0.6的流程设计

为何使用gooflow:1、兼容性好

                       2、扩展点很多可以个性化设计

                       3、配有api文档

                       4、json格式的数据传输

由于最近项目需要,急需设计一个流程,考虑到时间问题,和用户个性化的需求,没办法跟现在项目的后台集成,所以考虑到选择一款jquery插件,并通过存储过程来集成现在的业务模块。

 

直接上图了:

双击节点可以选择人员

双击连接线可以选择条件

使用gooflow版本为0.4的 网上可以搜到 另外当前版本有些bug需要自己改。需要提供帮助的可以加我QQ:512948935

gooflow版本为0.6

后台使用的是mvc+spring+NHibernate,主要是保存比较麻烦。

 前台js

<script type="text/javascript">
    var property = {
        toolBtns: ["start", "end", "task"],
        haveHead: true,
        headBtns: ["save", "undo", "redo", "reload"], //如果haveHead=true,则定义HEAD区的按钮
        haveTool: true,
        haveGroup: true,
        useOperStack: true
    };
    var remark = {
        cursor: "选择指针",
        direct: "转换连线",
        start: "开始结点",
        end: "结束结点",
        task: "任务结点",
        group: "组织划分框编辑开关"
    };
    var gooFlow, focusId, flow_title, flowID;
    $(function () {
        gooFlow = $.createGooFlow($("#flow"), property);
        flow_title = getUrlParam1("title");
        flowID = getUrlParam("flowID");
        if (flow_title != "") {
            //自适应调整
            gooFlow.reinitSize($(this).width() - 5, $(parent).height() - 25);
            gooFlow.setTitle(flow_title + "·流程绘制");
            parent.$('#div_layout').layout('panel', 'center').panel({
                onResize: function (width, height) {
                    gooFlow.reinitSize(width - 5, height - 30);
                }
            });
        }
        else
            gooFlow.reinitSize($(this).width() - 5, $(this).height() - 5);
        if (flowID == "") flowID = 0;
        gooFlow.setNodeRemarks(remark);
        //新建流程
        gooFlow.onBtnNewClick = function () {
            gooFlow.clearData();
        }
        //保存流程
        gooFlow.onBtnSaveClick = function () {
            var h = gooFlow.$bgDiv.height();
            $("<div class=\"datagrid-mask\"></div>").css({ display: "block", width: "100%", height: h }).appendTo(gooFlow.$bgDiv);
            $("<div class=\"datagrid-mask-msg\"></div>").html("数据正在保存中,请稍候……").appendTo(gooFlow.$bgDiv).css({
                display: "block",
                left: (gooFlow.$bgDiv.width() - 200) / 2,
                top: (h - 45) / 2
            });
            var obj = gooFlow.exportAlter();
            //节点
            var nodeData = "";
            for (var i in obj.nodes) {
                var id = gooFlow.$nodeData[i].ID == null ? 0 : gooFlow.$nodeData[i].ID;
                var userID = gooFlow.$nodeData[i].userID == null ? 0 : gooFlow.$nodeData[i].userID;
                nodeData += '{"ID": ' + id + ''
                                     + ',"FlowID": ' + flowID + ''
                                     + ',"NodeID": "' + i + '"'
                                     + ',"UserID": "' + userID + '"'
                                     + ',"UserName": "' + gooFlow.$nodeData[i].name + '"'
                                     + ',"NodeType":  "' + gooFlow.$nodeData[i].type + '"'
                                     + ',"NodeLeft":  ' + gooFlow.$nodeData[i].left + ''
                                     + ',"NodeTop":  ' + gooFlow.$nodeData[i].top + ''
                                     + ',"NodeWidth":  ' + gooFlow.$nodeData[i].width + ''
                                     + ',"NodeHeight":  ' + gooFlow.$nodeData[i].height + ''
                                     + ',"Marked": false},';
            }
            if (nodeData != "") {
                nodeData = "[" + $.trimend(nodeData, ',') + "]";
            }
            //连接线
            var lineData = "";
            for (var i in obj.lines) {
                var id = gooFlow.$lineData[i].ID == null ? 0 : gooFlow.$lineData[i].ID;
                var conditionID = gooFlow.$lineData[i].conditionID == null ? 0 : gooFlow.$lineData[i].conditionID;
                var lineM = gooFlow.$lineData[i].M == null ? 0 : gooFlow.$lineData[i].M;
                lineData += '{"ID": ' + id + ''
                                  + ',"FlowID": ' + flowID + ''
                                     + ',"LineID": "' + i + '"'
                                     + ',"ConditionID": ' + conditionID + ''
                                     + ',"ConditionName": "' + gooFlow.$lineData[i].name + '"'
                                     + ',"LineType":  "' + gooFlow.$lineData[i].type + '"'
                                     + ',"LineFrom":  "' + gooFlow.$lineData[i].from + '"'
                                     + ',"LineTo":  "' + gooFlow.$lineData[i].to + '"'
                                     + ',"LineM":  ' + lineM + ''
                                     + ',"Marked": false},';
            }
            if (lineData != "") {
                lineData = "[" + $.trimend(lineData, ',') + "]";
            }
            //区域
            var areaData = "";
            for (var i in obj.areas) {
                var id = gooFlow.$areaData[i].ID == null ? 0 : gooFlow.$areaData[i].ID;
                areaData += '{"ID": ' + id + ''
                                     + ',"FlowID": ' + flowID + ''
                                     + ',"AreaID": "' + i + '"'
                                     + ',"AreaName":  "' + gooFlow.$areaData[i].name + '"'
                                     + ',"AreaLeft":  ' + gooFlow.$areaData[i].left + ''
                                     + ',"AreaTop":  ' + gooFlow.$areaData[i].top + ''
                                     + ',"AreaWidth":  ' + gooFlow.$areaData[i].width + ''
                                     + ',"AreaHeight":  ' + gooFlow.$areaData[i].height + ''
                                     + ',"AreaColor":  "' + gooFlow.$areaData[i].color + '"'
                                     + ',"Marked": false},';
            }
            if (areaData != "") {
                areaData = "[" + $.trimend(areaData, ',') + "]";
            }
            if (nodeData == "" && lineData == "" && areaData == "") {
                $('.datagrid-mask-msg').remove();
                $('.datagrid-mask').remove();
                return;
            }
            $.ajax({
                type: "post",
                url: "/HR/BacthSave",
                data: { node: nodeData, line: lineData, area: areaData },
                success: function (data) {
                    if (data.status == 1) {
                        jqAlert('保存成功.', 'info', "reload");
                    }
                    else
                        jqAlert('保存失败:' + data, 'error')
                    $('.datagrid-mask-msg').remove();
                    $('.datagrid-mask').remove();
                }
            });
        }
        //刷新
        gooFlow.onFreshClick = function () {
            location.reload();
        }
        //单元节点双击事件
        gooFlow.$workArea.delegate(".ico + td", "dblclick", { inthis: gooFlow }, function (e) {
            var newId = $(this).parents(".GooFlow_item").attr("id");
            var $frame = $("#frame_choose_aud");
            if ($frame.attr("src") == undefined) {
                focusId = newId;
                $frame.attr("src", "/HR/BaseFlowChooseEmp");
            }
            else {
                if (focusId != newId) {
                    focusId = newId;
                    window.frames["choose_aud"].initData();
                }
            }
            $("#div_win_choose_aud").window('open');
        });
        //单元连接线双击事件
        var tmpClk = "PolyLine";
        if (GooFlow.prototype.useSVG != "")
            tmpClk = "g";
        $(gooFlow.$draw).delegate(tmpClk, "dblclick", { inthis: gooFlow }, function (e) {
            if (GooFlow.prototype.useSVG != "") {
                var $frame = $("#frame_choose_con");
                if ($frame.attr("src") == undefined) {
                    focusId = this.id;
                    $frame.attr("src", "/HR/BaseFlowCondition?typeID=" + getUrlParam("typeID"));
                }
                else {
                    if (focusId != this.id) {
                        focusId = this.id;
                        window.frames["choose_con"].unselect();
                    }
                }
                $("#div_win_choose_con").window('open');
            }
        });
        //操作单元删除事件
        gooFlow.onItemDel = function (id, type) {
            var delItem = gooFlow.getItemInfo(id, type);
            if (delItem.ID != null) {
                uiConfirm("确定要删除该单元吗.", function () {
                    $.post("/HR/DeleteFlowItem", { "id": id, "type": type }, function (data) {
                        if (data.status == 1) {
                            delItem.ID = null;
                            if (type == "node")
                                gooFlow.delNode(id);
                            else if (type == "line")
                                gooFlow.delLine(id);
                            else if (type == "area")
                                gooFlow.delArea(id);
                            return true;
                        }
                        else
                            jqAlert('删除失败:' + data, 'error')
                    });
                });
            }
            else
                return true
        }
        //初始化人员选择窗体
        showMyWindow($("#div_win_choose_aud"), '选择人员信息', 'icon-edit', '', 900, 450, true);
        //初始化人员选择窗体
        showMyWindow($("#div_win_choose_con"), '选择条件信息', 'icon-edit', '', 900, 450, true);
        //加载数据
        var h = gooFlow.$bgDiv.height();
        $("<div class=\"datagrid-mask\"></div>").css({ display: "block", width: "100%", height: h }).appendTo(gooFlow.$bgDiv);
        $("<div class=\"datagrid-mask-msg\"></div>").html("图形正在加载中,请稍候……").appendTo(gooFlow.$bgDiv).css({
            display: "block",
            left: (gooFlow.$bgDiv.width() - 200) / 2,
            top: (h - 45) / 2
        });
        var para = { "type": "get", "url": "/HR/LoadWorkArea?flowID=" + flowID, "success": onLoadSuccess, "error": onLoadError };
        gooFlow.loadDataAjax(para);
    });
    function onLoadSuccess(msg) {
        $('.datagrid-mask-msg').remove();
        $('.datagrid-mask').remove();
    }
    function onLoadError(status, errorThrown) {
        $('.datagrid-mask-msg').remove();
        $('.datagrid-mask').remove();
    }
    function backAudChoose(row) {
        gooFlow.setName(focusId, row.user_truename + "(" + row.user_no + ")", "node");
        var focusNode = gooFlow.getItemInfo(focusId, "node");
        focusNode.name = row.user_truename + "(" + row.user_no + ")";
        focusNode.userID = row.ID;
        $("#div_win_choose_aud").window('close');
    }
    function backConChoose(row) {
        gooFlow.setName(focusId, row.ConditionName, "line")
        var focusLine = gooFlow.getItemInfo(focusId, "line");
        focusLine.name = row.ConditionName;
        focusLine.conditionID = row.ID;
        $("#div_win_choose_con").window('close');
    }
</script>

  后台处理

 public ActionResult BaseFlowPicture()
       {
           return View();
       }
       public ActionResult BacthSave(string node = "", string line = "", string area = "")
       {
           try
           {
               if (node != "")
               {
                   List<Q_HR_WorkFlow_Node> nodes = JSONStringToList<Q_HR_WorkFlow_Node>(node);
                   int s = nodes.Where(c => c.NodeType == "start").Count();
                   int e = nodes.Where(c => c.NodeType == "end").Count();
                   if (s != 1)
                       throw new Exception("请设置一个开始节点.");
                   if (e != 1)
                       throw new Exception("请设置一个结束节点.");
                   Q_HR_WorkFlow_NodeManage.BatchSave(nodes);
               }
               if (line != "")
               {
                   List<Q_HR_WorkFlow_Line> lines = JSONStringToList<Q_HR_WorkFlow_Line>(line);
                   Q_HR_WorkFlow_LineManage.BatchSave(lines);
               }
               if (area != "")
               {
                   List<Q_HR_WorkFlow_Area> areas = JSONStringToList<Q_HR_WorkFlow_Area>(area);
                   Q_HR_WorkFlow_AreaManage.BatchSave(areas);
               }
               return Json(new { status = 1 }, JsonRequestBehavior.AllowGet);
           }
           catch (Exception ex)
           {
               return Content(ex.Message);
           }
       }
       public string LoadWorkArea(int flowID = 0)
       {
           DataTable nodes = Q_HR_WorkFlow_NodeManage.GetList(flowID);
           DataTable lines = Q_HR_WorkFlow_LineManage.GetList(flowID);
           IList<Q_HR_WorkFlow_Area> areas = Q_HR_WorkFlow_AreaManage.GetList(flowID);
           string jsonStr = "{";
           string alt;
           //jsonStr += "\"initNum\":" + Q_HR_WorkFlow_NodeManage.GetInitNum() + ",";
           if (nodes.Rows.Count > 0)
           {
               jsonStr += "\"nodes\":{";
               foreach (DataRow row in nodes.Rows)
               {
                   alt = "false";
                   if (row["NodeType"].ToString() == "start" || row["NodeType"].ToString() == "end")
                       alt = "true";
                   jsonStr += "\"" + row["NodeID"] + "\":{"
                           + "\"ID\":" + row["ID"] + ""
                           + ",\"name\":\"" + row["UserName"] + "(" + row["user_no"] + ")\""
                           + ",\"userID\":" + row["UserID"] + ""
                           + ",\"type\":\"" + row["NodeType"] + "\""
                           + ",\"left\":" + row["NodeLeft"] + ""
                           + ",\"top\":" + row["NodeTop"] + ""
                           + ",\"width\":" + row["NodeWidth"] + ""
                           + ",\"height\":" + row["NodeHeight"] + ""
                           + ",\"alt\":" + alt + ""
                           + ",\"mark\":" + row["Marked"].ToString().ToLower() + ""
                           + "},";
               }
               jsonStr = jsonStr.TrimEnd(',') + "},";
           }
           if (lines.Rows.Count > 0)
           {
               jsonStr += "\"lines\":{";
               foreach (DataRow row in lines.Rows)
               {
                   jsonStr += "\"" + row["LineID"] + "\":{"
                           + "\"ID\":" + row["ID"] + ""
                           + ",\"name\":\"" + row["ConditionName"] + "\""
                           + ",\"conditionID\":" + row["ConditionID"] + ""
                           + ",\"type\":\"" + row["LineType"] + "\""
                           + ",\"from\":\"" + row["LineFrom"] + "\""
                           + ",\"to\":\"" + row["LineTo"] + "\""
                           + ",\"M\":" + row["LineM"] + ""
                           + ",\"mark\":" + row["Marked"].ToString().ToLower() + ""
                           + "},";
               }
               jsonStr = jsonStr.TrimEnd(',') + "},";
           }
           if (areas.Count > 0)
           {
               jsonStr += "\"areas\":{";
               foreach (Q_HR_WorkFlow_Area area in areas)
               {
                   jsonStr += "\"" + area.AreaID + "\":{"
                           + "\"ID\":" + area.ID + ""
                           + ",\"name\":\"" + area.AreaName + "\""
                           + ",\"left\":" + area.AreaLeft + ""
                           + ",\"top\":" + area.AreaTop + ""
                           + ",\"width\":" + area.AreaWidth + ""
                           + ",\"height\":" + area.AreaHeight + ""
                           + ",\"color\":\"" + area.AreaColor + "\""
                           + "},";
               }
               jsonStr = jsonStr.TrimEnd(',') + "},";
           }
           jsonStr = jsonStr.TrimEnd(',') + "}";
           return jsonStr;
       }
       public ActionResult DeleteFlowItem(string id, string type)
       {
           try
           {
               if (type.Equals("node"))
                   Q_HR_WorkFlow_NodeManage.DeleteFlowNode(id, type);
               else if (type.Equals("line"))
                   Q_HR_WorkFlow_LineManage.DeleteFlowLine(id, type);
               else if (type.Equals("area"))
                   Q_HR_WorkFlow_AreaManage.DeleteFlowArea(id, type);
               return Json(new { status = 1 }, JsonRequestBehavior.AllowGet);
           }
           catch (Exception ex)
           {
               return Content(ex.Message);
           }
       }

属性名称

作用

$id

装载整个UI的DOM对象的ID。

$bgDiv

最父框架的DIV。

$tool

左侧工具栏JQ对象。

$head

顶部栏标题标签及工具栏按钮。

$title

载入的流程图的名称。

$nodeRemark

左侧工具栏中每一种结点或按钮的说明文字,JSON格式,key为按钮类型名,value为用户自定义文字说明。

$nowType

当前要绘制的对象类型,开始时为“cursor”,即不绘制任何元素,只是作为鼠标指针进行元素选定。

$lineData={}

转换线数据Map集,以id为key,value为详细数据JSON对象。

$lineCount=0

转换线数据的数量。

$nodeData={}

节点数据Map集,以id为key,value为详细数据JSON对象。

$nodeCount=0

节点数据的数量。

$areaData={}

分组区数据Map集,以id为key,value为详细数据JSON对象。

$areaCount=0

分组区数据的数量。

$lineDom={}

转换线DOM展示对象Map集,以id为key,value为详细在DOM对象。

$nodeDom={}

节点JQ展示对象Map集,以id为key,value为详细在JO对象。

$areaDom={}

分组区JQ展示对象Map集,以id为key,value为详细在JO对象。

$max

计算默认ID值的起始SEQUENCE,默认不填时为1。

$focus

当前被选定的结点/转换线ID,如果没选中或者工作区被清空,则为""。

$cursor

鼠标指针在工作区内的样式,初始时为default。

$editable

当前工作区是否可编辑,即是编辑模式还是仅浏览模式。

$workArea

装载结点/线条/分组区域的工作区。

$draw

画矢量线条的容器,处于工作区中。

$group

仅用来装配分组区域DOM元素的容器,处于工作区中。

$ghost

专门用在移动、重置大小等操作时,给用户操作的半透明浮动区。

$textArea

双击操作对象后出现的浮动文本域,用来写重命名方法setName所需的新名称传参。

$lineMove

操作移动折线的中段时用到的浮动DIV

$lineOper

选定一条转换线后出现的浮动操作栏,有改变线的样式和删除线等按钮。

//以下是当初始化的参数property.useOperStack=true且$editable=true时,才存在的属性:

$undoStack=[]

“撤销操作”栈。

$redoStack=[]

重做操作栈。

$isUndo

事务操作标志位,内部调用

$deletedItem={}

在流程图的编辑操作中被删除掉的元素ID集合,元素ID为KEY,元素类型(node,line.area)为VALUE


GooFlow对象供使用者调用的方法集

方法名称

作用

setNodeRemarks(remark)

设定左侧工具栏中每一种结点或按钮的说明文字,传参是JSON格式,key为按钮类型名,value为用户自定义文字说明。

switchToolBtn(type)

切换左边工具栏按钮,传参type表示切换成哪种类型的按钮

addNode(id,json)

增加一个结点,传参json内容结构与$nodeData的每个属性单元一样。

getItemInfo(id,type)

根据id这个KEY,和要获取的数据类型type(有”node”,”line”,”area”三种取值),返回相应的结点json数据单元

blurItem()

取消所有结点/连线被选定的状态

focusItem(id,bool)

选定某个结点/转换线;传参bool:TRUE决定了要触发选中事件,FALSE则不触发选中事件,多用在程序内部调用。

moveNode(id,left,top)

移动一个结点到一个新的位置

setName(id,name,type)

设置结点/连线/分组区域的文字信息;传参id为序列,name为新的名称,type为更名对象的数据类型(有”node”,”line”,”area”三种取值)

resizeNode(id,width,height)

重新设置结点的尺寸,开始/结束类型的结点不支持该方法

delNode(id)

删除结点

setTitle(text)

设置流程图的名称

loadData(data)

载入一组数据JSON格式的流程图数据,传参data中有title,nodes,lines,areas四个KEY的数据,还有一个可选属性数据initNum:ID起始序列号最大数字+1——由于绘制的新单元的ID都是按一定序列号及规则自动生成的,为了防止新载入的数据的ID与编辑时新加入的ID值有重复,将给设计器对象对于新生成单元的ID序列一个新的起始序列号;如果传参JSON中没有这个属性,也可以在调用loadData方法前修改设计器对象的$max属性值(其实loadData方法执行时会检查传参中如果有initNum时,将自动给设计器对象的$max赋上此值);

nodes,lines,areas都为一组{key:value}式的Map数据,内容结构分别与GooFlow对象属性中的$nodeData,$lineData,$areaData一致.

loadDataAjax(para)

用AJAX方式,远程读取一组数据;

参数para为JSON结构,与JQUERY中$.ajax()方法的传参一样

需要后台异步返回JSON格式的msg结果,其内容格式与loadData方法的传参一样。

exportData()

把画好的结束导出到一个本函数返回的变量中(其实也可以直接访问GooFlow对象的$nodeData,$lineData,$areaData这三个JSON属性)

exportAlter()

//只把本次编辑流程图中作了变更(包括增删改)的元素导出到一个变量中,以方便用户每次编辑载入的流程图后只获取变更过的数据

transNewId(oldId,newId,type)

变更元素的ID,一般用于快速保存后,将后台返回新元素的ID更新到页面中;type为元素类型(节点,连线,区块)

clearData()

清空工作区及已载入的数据

destrory()

销毁自己

addLine(id,json)

增加一条线,传参json内容结构与$lineData的每个属性单元一样。

setLineType(id,newType)

重新设置连线的样式. 传参newType的取值有:"sl"直线, "lr"中段可左右移动型折线, "tb"中段可上下移动型折线

setLineM(id,M)

设置折线中段的X坐标值(可左右移动时)或Y坐标值(可上下移动时);直线不支持此方法

delLine(id)

删除转换线

markItem(id,type,mark)

//用颜色标注/取消标注一个结点或转换线,常用于显示重点或流程的进度。

       //这是一个在编辑模式中无用,但是在纯浏览模式中非常有用的方法,实际运用中可用于跟踪流程的进度。

//传参:id是操作单元对象唯一序列号;type是操作单元类型(“node”或者”line”,分组区域不支持此方法);mark为布尔值,表示是否标注/取消标注某个ID值的数据单元对象

addArea(id,json)

增加一个分组区域,传参json内容结构与$areaData的每个属性单元一样。

moveArea(id,left,top)

移动分组区域到新的位置上.

delArea(id)

删除分组区域

setAreaColor(id,color)

设置分组区域的颜色,传参color为颜色样式,只有”red”,”yellow”,”blue”,”green”四种取值

resizeArea(id,width,height)

重新设置区分组区域的尺寸

      

reinitSize(width,height)

重构整个流程图设计器的宽高,在浏览器窗口大小改变或者父容器宽高改变时,执行这个方法能让设计器重新适应新的宽高显示。

//以下是当初始化的参数property.useOperStack=true时,才存在的方法:

pushOper(funcName,paras)

仅供内部方法调用的方法:把对工作区内的数据单元编辑操作(增/删/改/重命名/移动/标注等)加入整条管理栈中,好进入撤销/重做的控制;

注意:将为了节省浏览器内存空间,undo/redo中的操作缓存栈,最多只可放40步操作;超过40步时,将自动删掉最旧的一个缓存。

pushExternalOper

(func,jsonPara)

//将外部的方法加入到GooFlow对象的事务操作堆栈中,在过后的undo/redo操作中可以进行控制,一般用于对流程图以外的附加信息进行编辑的事务撤销/重做控制;

//传参func为要执行方法对象,jsonPara为外部方法仅有的一个面向字面的JSON传参或者数据,由JSON对象或数组带入所有要传的信息;

//提示:为了让外部方法能够被UNDO/REDO,需要在编写这些外部方法实现时,加入对该方法执行后效果回退的另一个执行方法的pushExternalOper。

undo()

撤销最近一次操作

redo()

重做最近一次被撤销的操作

在线案例二、自定义流程gooflow.08 demo在线演示

一、功能简介

gooflow功能清单
1、自定义流程绘制
2、自定义属性添加
3、支持3种步骤类型
普通审批步骤
自动决策步骤
手动决策步骤

4、决策方式(支持js决策,sql语句决策)

5、审批人员参与方式,可以自定配置,系统目前自带(员工,部门,岗位,sql语句4种方式)
6、响应方式(支持多人审批通过,和单人审批通过)
7、事件执行方式(审批通过后可以触发配置事件)
8、消息提醒(支持实时提醒)
9、流程决策条件,自定义配置

流程审批功能
1、提交
2、退回
3、退回上一步
4、退回到开始节点
5、表单退回
6、审批不同过
7、附件上传
8、生成word文档
9、查看流程图。

二、流程界面展示

1.流程设计主界面(右边显示流程元素的属性)

2.提供了自动决策和手动决策2中方案,方案可以是js脚本,或者sql语句。

3.流程参与者,提供了3种类型。

4.流程条件:每一个流程条件都有关键值,对应到决策方案中.

5.自定义属性:方便自己新功能的扩展

6.任务列表也

7.流转界面

 

 

在线案例三、修正版gooflow流程解决方案(源码分享+在线演示+UI地址下载)

一、功能简介

gooflow功能清单
1、自定义流程绘制
2、自定义属性添加
3、支持3种步骤类型
普通审批步骤
自动决策步骤
手动决策步骤

4、决策方式(支持js决策,sql语句决策)

5、审批人员参与方式,可以自定配置,系统目前自带(员工,部门,岗位,sql语句4种方式)
6、响应方式(支持多人审批通过,和单人审批通过)
7、事件执行方式(审批通过后可以触发配置事件)
8、消息提醒(支持实时提醒)
9、流程决策条件,自定义配置

10、版本控制

11、后台管理

二、流程审批功能
1、提交
2、退回
3、退回上一步
4、退回到开始节点
5、表单退回
6、审批不通过
7、附件上传
8、传阅、转办、撤回、查看流程图。

9、提供WebAPI接口

10、可配置审批参与者数据源

三、接口说明

作用

接口名称

参数

返回值

获取审批列表

GetApprovalList

1.(string)userdata

2.(int)page

3.(int)pagesize

4.(int)isOver

5.(string)

flowLevel

6.(string)where

Dynamic->JsonData

 

 

获取审批列表汇总信息

LoadApprovalListSummary

1.(string)userData

Dynamic->JsonData

 

初始化流程状态

InitFlowState

1.string userData

2.string flowNo

3.int appID

4.string formHtml

5.string formData

6.string formUrl

Dynamic->

status = ?

flowID = ?

获取当前步骤信息

GetCurrentStepInfo

1.string userData

2.int approvalID = 0

3.int? flowID = 0

4.int? appID = 0

Dynamic ->

{

status = ?

stepData =?

isBack = ?

isTurnRead =? isTurnRead=?

isTurnDo = ?

};

获取审批参与者

FindFlowApprovers

1.string userData

2.int flowID

3.int approvalID

4. int appID

5. string toNodeID = ""

Dynamic ->{

status = ?

data = ?

}

获取审批意见

GetApprovalOpinions

  1. int flowID
  2. int appID

Dynamic ->

{

data = ?

}

获取下个节点(所有)

GetNextFlowNodes

1.int flowID

2.int appID

3.int approvalID

Dynamic ->

{

status = ?

 data = ?

 }

获取决策方案

GetFlowDecisionModes

  1. int flowID
  2. int appID
  3. int approvalID

Dynamic ->

{

status = ?

 data = ?

 }

流转主要功能接口

FlowAction

1.string userData

2.string actionType

3.int stateID

4.int approvalID

5.int appID;

6.bool isPass

7.string opinion

8.string formName

9.string participantJson                10.string participantValue                11.int level                12.int turnToDoID = 0

Dynamic ->

{

status = ?

 data = ?

 }

获取待阅

列表数据

GetTurnToReadPageList

1.string userData

2.int page                3.int pagesize

4.int isRead

5.string where

Dynamic->JsonData

查找传阅参与者

FindFlowTurnToReaders

1.string userData,

2.int flowID,

3.string nodeID

Dynamic ->

{

status = ?,

data = ?

 }

浏览传阅表单

ReadApprovalForm

1.tring userData

2.int approvalID

Dynamic ->

{

status = ?

}

获取传阅数据

GetTurnToReadList

int stateID

Dynamic->JsonData

获取代办参与者数据

FindFlowTurnToApprovers

  1. string userData
  2.  int flowID
  3.  string nodeID

Dynamic ->

{

status = ?,

data=?

 }

获取代办数据

GetTurnToDoPageList

1.string userData

2.int pag                3.int pagesize                 4.int isOver                 5.string where

Dynamic->JsonData

获取流程图流转标记

GetFlowElementMarked

1.int flowID

2. int appID

Dynamic ->

{

status = ?,

data=?

 }

 

 

四、流转界面

源码:截图


参考博客:

http://www.cnblogs.com/tangxf/p/7609105.html

Gooflow0.6 UI界面下载

https://pan.baidu.com/s/1dD9C1Tf

GooFlow0.8 ui界面下载

https://pan.baidu.com/s/1sjqsdDb

GooFlow1.1 ui界面下载

https://pan.baidu.com/s/1o8ebUdk

GooFlow2.0

http://www.cnblogs.com/tangxf/p/7609105.html


猜你喜欢

转载自blog.csdn.net/WYpersist/article/details/80568095