前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C# 实现改造 GooFlow 流程图插件与数据库应用的结合

C# 实现改造 GooFlow 流程图插件与数据库应用的结合

作者头像
初九之潜龙勿用
发布2024-08-14 15:02:18
1610
发布2024-08-14 15:02:18
举报
文章被收录于专栏:技术文章

关于 GooFlow

GooFlow 一个基于 Jquery/FontAwesome 的流程图/架构图画图插件,本文介绍的是基于JS的一个版本,能够适用于大部分支持H5的浏览器。通过创建画布,我们可以在其上通过工具栏绘制想要绘制的流程图/框/线等,如下图所示:

图中包括操作工具栏(顶部)、绘图工具栏(左侧)和绘制画布区域,左上角显示的是当前流程的名称。 具体的操作我们不再详述,本文将介绍通过改造后的 GooFlow 简化版本,结合数据库满足实际的开发需求。

功能需求

我们需要实现一个审批流程,在关键流程节点可能会添加审批人信息,通过GoolFlow绘制并显示,则更加友好和直观, 基本需要实现如下功能:

1、改造 GooFlow JS 程序,简化绘制工具栏。

2、设计相关数据库数据表保存流程图设计相关信息、节点明细信息等。

3、改造 GooFlow 操作工具栏,满足实际应用。

范例运行环境

操作系统: Windows Server 2019 DataCenter

GooFlow 版本:GooFlow V1 JS 版

数据库:Microsoft SQL Server 2016

.net版本: .netFramework4.7.1 或以上

开发工具:VS2019 C#

设计数据表

流程项目表

cc_flow 表记录项目信息,主要说明见下表:

序号

字段名

类型

说明

1

cid

uniqueidentifier

记录唯一标识

2

flowName

nvarchar(50)

流程项目名称

3

nodeCount

int

节点总个数

4

desript

nvarchar(50)

项目描述

5

flowJSON

nvarchar(MAX)

流程全部 JSON 数据

6

sys_insuser

nvarchar(100)

创建信息用户名

7

sys_instime

datetime

创建时间

8

sys_upduser

nvarchar(100)

最后修改信息用户名

9

sys_updtime

datetime

修改时间

创建脚本如下:

代码语言:javascript
复制
CREATE TABLE [dbo].[cc_flow](
	[cid] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
	[flowName] [nvarchar](50) NOT NULL,
	[nodeCount] [int] NULL,
	[desript] [nvarchar](100) NULL,
	[flowJSON] [nvarchar](max) NULL,
	[sys_insuser] [nvarchar](100) NULL,
	[sys_instime] [datetime] NULL,
	[sys_upduser] [nvarchar](100) NULL,
	[sys_updtime] [datetime] NULL,
 CONSTRAINT [PK_cc_flow] PRIMARY KEY CLUSTERED 
(
	[cid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
 CONSTRAINT [IX_cc_flow] UNIQUE NONCLUSTERED 
(
	[flowName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

ALTER TABLE [dbo].[cc_flow] ADD  CONSTRAINT [DF_cc_flow_cid]  DEFAULT (newid()) FOR [cid]
GO
流程项目节点明细表

cc_flowNodes 表记录了项目绘制节点的所有信息明细情况,主要说明见下表:

序号

字段名

类型

说明

1

cid

uniqueidentifier

记录唯一标识

2

nodeId

nvarchar(50)

节点ID

3

nodeName

nvarchar(50)

节点流程名称

4

desript

nvarchar(100)

节点流程描述

5

parentNodeId

nvarchar(50)

父节点ID

6

projectCid

uniqueidentifier

流程项目ID,所属的项目唯一标识

7

sortid

int

节点排序

8

sys_insuser

nvarchar(100)

创建信息用户名

9

sys_instime

datetime

创建时间

10

sys_upduser

nvarchar(100)

最后修改信息用户名

11

sys_updtime

datetime

修改时间

创建脚本如下:

代码语言:javascript
复制
CREATE TABLE [dbo].[cc_flowNodes](
	[cid] [uniqueidentifier] NOT NULL,
	[nodeId] [nvarchar](50) NOT NULL,
	[nodeName] [nvarchar](50) NOT NULL,
	[desript] [nvarchar](100) NULL,
	[parentNodeId] [nvarchar](50) NULL,
	[projectCid] [uniqueidentifier] NOT NULL,
	[sortid] [int] NULL,
	[sys_insuser] [nvarchar](100) NULL,
	[sys_instime] [datetime] NULL,
	[sys_upduser] [nvarchar](100) NULL,
	[sys_updtime] [datetime] NULL
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[cc_flowNodes] ADD  CONSTRAINT [DF_cc_flowNodes_cid]  DEFAULT (newid()) FOR [cid]
GO
流程项目节点审批人表

cc_flowNodeAccounts 表记录了项目关键节点的参与审批人情况,主要说明见下表:

序号

字段名

类型

说明

1

cid

uniqueidentifier

记录唯一标识

2

nodeId

nvarchar(50)

节点ID

3

AccountCid

uniqueidentifier

所属的人员信息ID

4

desript

nvarchar(100)

描述,可以记录诸如姓名相关的一些信息

5

role

nvarchar(50)

审批人权限(如决策、抄送)

6

projectCid

uniqueidentifier

流程项目ID,所属的项目唯一标识

7

sys_insuser

nvarchar(100)

创建信息用户名

8

sys_instime

datetime

创建时间

9

sys_upduser

nvarchar(100)

最后修改信息用户名

10

sys_updtime

datetime

修改时间

创建脚本如下:

代码语言:javascript
复制
CREATE TABLE [dbo].[cc_flowNodeAccounts](
	[cid] [uniqueidentifier] NOT NULL,
	[projectCid] [uniqueidentifier] NOT NULL,
	[AccountCid] [uniqueidentifier] NOT NULL,
	[descript] [nvarchar](100) NULL,
	[nodeId] [nvarchar](50) NOT NULL,
	[role] [nvarchar](50) NULL,
	[sys_insuser] [nvarchar](100) NULL,
	[sys_instime] [datetime] NULL,
	[sys_upduser] [nvarchar](100) NULL,
	[sys_updtime] [datetime] NULL
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[cc_flowNodeAccounts] ADD  CONSTRAINT [DF_cc_flowNodeBuss_cid]  DEFAULT (newid()) FOR [cid]
GO
人员信息表

accounts 表审批人的基本个人情况,主要说明见下表:

序号

字段名

类型

说明

1

cid

uniqueidentifier

记录唯一标识

2

name

nvarchar(50)

姓名

3

nickName

nvarchar(50)

昵称

创建脚本如下:

代码语言:javascript
复制
CREATE TABLE [dbo].[accounts](
	[cid] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
	[name] [nvarchar](50) NULL,
	[nickname] [nvarchar](500) NULL,
 CONSTRAINT [PK_wxmp_accounts] PRIMARY KEY CLUSTERED 
(
	[cid] ASC
)
)
GO

ALTER TABLE [dbo].[accounts] ADD  CONSTRAINT [DF_wxmp_accounts_cid]  DEFAULT (newid()) FOR [cid]
GO

示例代码

流程图主功能

本示例代码包含后端、前端及 JS 代码,代码如下:

代码语言:javascript
复制
<%@ Page Language="C#" AutoEventWireup="true" MaintainScrollPositionOnPostback="true"  ValidateRequest="FALSE" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>

<script language="C#" runat="server">
    public CosysJaneCommonAPI.CODAL dal = new CosysJaneCommonAPI.CODAL();
    public DateTime dt = DateTime.Now;
    void Page_load(Object sender, EventArgs e)
    {
        dal.RunAt = Form;
        if (Page.IsPostBack == true) return;
        dal.ConnKeyString = "JaneConnectionCloud";
        ArrayList paras = new ArrayList();
        paras.Clear();
        paras.Add(new SqlParameter("a", "2"));
        dal.simpledatalist("select cid,flowName from cc_flow order by flowName ", paras, "cid", "flowName",flowlist, true, "", "选择打开已创建流程");

     }

    protected void saveflow_Click(object sender, EventArgs e)
    {
        dal.ConnKeyString = "JaneConnectionCloud";

        ArrayList paras = new ArrayList();
        paras.Clear();
        paras.Add(new SqlParameter("flowname", x_flowname.Text));
        dal.RowsCount = 0;
        dal.ErrorMessage = "";
        dal.ExecDbScripts("insert into cc_flow (flowName) values(@flowname) ", paras);
        if (dal.RowsCount > 0)
        {
            tip.Text = "创建成功!";
            flowpanel.Visible = true;
        }else
        {
            if (dal.ErrorMessage.IndexOf("重复键") != -1)
            {
                dal.RowsCount = 0;
                dal.ErrorMessage = "";
                paras.Clear();
                paras.Add(new SqlParameter("flowname", x_flowname.Text));
                object rv = dal.GetDataSet("select * from  cc_flow where flowname=@flowname ", paras);
                if (dal.RowsCount > 0)
                {
                    DataSet ds = rv as DataSet;
                    DataTable dt = ds.Tables[0];
                    x_cid.Text = dt.Rows[0]["cid"].ToString();
                    x_flowJSON.Text = dt.Rows[0]["flowJSON"].ToString();
                    
                    tip.Text = "打开成功!";
                    flowpanel.Visible = true;
                }
                else
                {
                    tip.Text = dal.ErrorMessage;
                    flowpanel.Visible = false;
                }
            }
            else
            {
                tip.Text = dal.ErrorMessage;
                flowpanel.Visible = false;
            }
        }
    }

    protected void updflow_Click(object sender, EventArgs e)
    {
        dal.ConnKeyString = "JaneConnectionCloud";

        ArrayList paras = new ArrayList();

        Newtonsoft.Json.Linq.JObject jsonObj = Newtonsoft.Json.Linq.JObject.Parse(x_flowJSON.Text);
        string nodelist = "";
        foreach (Newtonsoft.Json.Linq.JProperty jt in  jsonObj["nodes"])
        {
            nodelist+=jt.Name+",";
        }
        string cid = x_cid.Text;

        dal.ConnKeyString = "JaneConnectionCloud";

        paras.Clear();
        paras.Add(new SqlParameter("cid", cid));
        dal.RowsCount = 0;
        dal.ErrorMessage = "";
        dal.ExecDbScripts("delete cc_flowNodes where projectCid=@cid ", paras);

        string[] la = nodelist.Split(',');
        int added = 0;
        for (int i = 0; i < la.GetLength(0); i++)
        {
            if (la[i] != "")
            {
                paras.Clear();
                paras.Add(new SqlParameter("projectCid", cid));
                paras.Add(new SqlParameter("parentNodeId", (i == 0 ? cid : la[i - 1])));
                paras.Add(new SqlParameter("nodeId", la[i]));
                paras.Add(new SqlParameter("nodeName", jsonObj["nodes"][la[i]]["name"].ToString()));
                paras.Add(new SqlParameter("sortid", i + 1));
                dal.RowsCount = 0;
                dal.ErrorMessage = "";
                dal.ExecDbScripts("insert into cc_flowNodes(projectCid,parentNodeId,nodeId,nodeName,sortid) values(@projectCid,@parentNodeId,@nodeId,@nodeName,@sortid) ", paras);
                if (dal.RowsCount > 0)
                {
                    added++;
                }
            }
        }

        
        
        paras.Clear();
        paras.Add(new SqlParameter("cid", x_cid.Text));
        paras.Add(new SqlParameter("flowName",x_flowname.Text));
        paras.Add(new SqlParameter("flowJSON", x_flowJSON.Text));
        dal.RowsCount = 0;
        dal.ErrorMessage = "";
        dal.ExecDbScripts("update cc_flow set flowName=@flowname,flowJSON=@flowJSON where cid=@cid ", paras);
        if (dal.RowsCount > 0)
        {
            tip.Text = "更新成功!";
        }
        else
        {
            tip.Text = dal.ErrorMessage;
        }

    }

    protected void flowlist_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (flowlist.SelectedValue == "")
        {
            return;
        }
        
        dal.ConnKeyString = "JaneConnectionCloud";

        ArrayList paras = new ArrayList();
        dal.RowsCount = 0;
        dal.ErrorMessage = "";
        paras.Clear();
        paras.Add(new SqlParameter("cid",flowlist.SelectedValue));
        object rv = dal.GetDataSet("select * from  cc_flow where cid=@cid ", paras);
        if (dal.RowsCount > 0)
        {
            DataSet ds = rv as DataSet;
            DataTable dt = ds.Tables[0];
            x_cid.Text = dt.Rows[0]["cid"].ToString();
            x_flowname.Text = dt.Rows[0]["flowName"].ToString();
            x_flowJSON.Text = dt.Rows[0]["flowJSON"].ToString();

            tip.Text = "打开成功!";
            flowpanel.Visible = true;
        }
        else
        {
            tip.Text = dal.ErrorMessage;
            flowpanel.Visible = false;
        }

    }
</script>        

<!DOCTYPE html>
<html lang="cn" >
<head>
  <meta charset="UTF-8">
  <title></title>
<link rel="stylesheet" href="dist/GooFlow.min.css?v=10" />
<link rel="stylesheet" href="fontawesome/css/font-awesome.min.css" />
</head>

<script src="dist/jquery.min.js"></script>
<script src="dist/GooFlow.js?v=7"></script>
<body>
  <form runat="server">
  <div style=" display:flex">
  <asp:TextBox ID="x_flowname" placeholder="输入项目名称" runat="server"></asp:TextBox>
  <asp:Button ID="saveflow" Text="创建项目" runat="server" onclick="saveflow_Click"></asp:Button>
  <asp:Button ID="updflow" Text="更新项目" style=" display:none" runat="server" onclick="updflow_Click" ></asp:Button>
  <asp:TextBox ID="x_cid" placeholder="cid" style="display:none" ReadOnly="true" runat="server"></asp:TextBox>
  <asp:DropDownList ID="flowlist" runat="server" AutoPostBack="true"
          onselectedindexchanged="flowlist_SelectedIndexChanged"></asp:DropDownList>
  </div>
  <div style=" margin:10px; display:flex">
  <asp:Label ID="tip" Text="这是一些提示信息..." runat="server"></asp:Label>
  </div>
      <iframe id="tframe" width="500" height="400" style=" display:none;z-index:99;position:absolute;" runat="server"></iframe>
    <div id="flowpanel" visible="false" runat="server">
</div>
    <div>
  <asp:TextBox ID="x_flowJSON" Rows="10" style="display:none"  width="100%" TextMode="MultiLine" runat="server"></asp:TextBox>
    </div>
  </form>
</body>
</html>
<script language="javascript" type="text/javascript">
        var tframe=$('#tframe');
        var curnode=null;
        var flowpanel=null;
        var sortBy = function (filed, rev, primer) {
            rev = (rev) ? -1 : 1;
            return function (a, b) {
                a = a[filed];
                b = b[filed];
                if (primer && typeof (primer) != 'undefined') {
                    a = primer(a);
                    b = primer(b);
                }else{
			        if(!isNaN(a) && !isNaN(a)){
				        a = Number(a);
				        b = Number(b);
			        }
		        }
                if (a < b) { return rev * -1; }
                if (a > b) { return rev * 1; }
                return 1;
            }
        };


        $(function(){
            var options={initLabelText:"未命名",toolBtns:["task","chat","state"],toolBtnRemarks:{cursor:"选择指针",direct:"连线",task:"任务结点",chat:"决策结点",state:"状态结点",group:"组织区域框"},headBtns:["save","undo","redo","new","expand"],headBtnRemarks:['保存','撤销','重做','清空画布','结点设置']};
            flowpanel = $('#flowpanel').createGooFlow(options);
            var flowpanelData = {
                areas: {
                    flowpanel_area_17: {
                        color: "yellow",
                        height: 300,
                        left: 40,
                        name: "部门一",
                        top: 30,
                        width: 150,
                    },
                    flowpanel_area_18: {
                        color: "blue",
                        height: 300,
                        left: 200,
                        name: "部门二",
                        top: 30,
                        width: 150,
                    },
                    flowpanel_area_19: {
                        color: "green",
                        height: 300,
                        left: 360,
                        name: "部门三",
                        top: 30,
                        width: 150,
                    },
                    flowpanel_area_20: {
                        color: "red",
                        height: 300,
                        left: 520,
                        name: "部门四",
                        top: 30,
                        width: 150,
                    },
                },
                lines: {
                    flowpanel_line_11: {
                        from: "flowpanel_node_1",
                        marked: false,
                        name: "",
                        to: "flowpanel_node_2",
                        type: "sl",
                    },
                },
                nodes: {
                    flowpanel_node_1: {
                        height: 24,
                        left: 70,
                        name: "节点流程1",
                        top: 66,
                        type: "chat",
                        width: 86,
                        sortid:1,
                        id:"flowpanel_node_1",
                    },
                    flowpanel_node_2: {
                        height: 24,
                        left: 240,
                        name: "节点流程2",
                        top: 132,
                        type: "state",
                        width: 86,
                        sortid:2,
                        id:"flowpanel_node_2",
                    },
                }
            };
            flowpanel.loadData(flowpanelData);

            if($('#x_flowJSON').val()!=""){
                flowpanel.clearData();
                flowpanel.loadData($.parseJSON($('#x_flowJSON').val()));
                alert("加载流程图成功");
            }
            flowpanel.setTitle($('#x_flowname').val());
            $('#flowpanel').css('backgroundColor','silver');
            $('#flowpanel').css('borderColor','silver');
           
            var obj = flowpanel.exportData();

            flowpanel.onExpandClick=function(){
                if(curnode==null) return;
                 var x=(curnode.offset().left+parseInt(curnode.css('width'),10))+'px';
                 var y=curnode.offset().top+'px';
                 tframe.css('left',x);
                 tframe.css('top',y);
                 tframe.attr('src','test_server.aspx?cid='+$('#x_cid').val()+'&nid='+curnode.selector.substring(1));
                 tframe.css('display',(tframe.css('display')=='none'?'':'none'));
                 
            }

            flowpanel.onBtnSaveClick=function(){
                  $('#x_flowJSON').val(JSON.stringify(this.exportData()));
                  $('#updflow').click();
            }
            

            flowpanel.onItemFocus=function(id,type){
                 flowpanel.focusItem(id,false);
                 curnode=$("#"+id);
                 tframe.css('display','none');
            }
       });

</script>
设置审批人信息

页面名称为test_server.aspx,在流程图主功能的JS代码部分有体现, 本示例代码包含后端、前端及 JS 代码,代码如下:

代码语言:javascript
复制
<%@ Page Language="C#" AutoEventWireup="true" enableEventValidation="false" MaintainScrollPositionOnPostback="true"  ValidateRequest="FALSE" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>

<script language="C#" runat="server">
    public CosysJaneCommonAPI.CODAL dal = new CosysJaneCommonAPI.CODAL();
    public DateTime dt = DateTime.Now;
    void Page_load(Object sender, EventArgs e)
    {
        dal.RunAt = Form;
        if (Page.IsPostBack == true) return;
        ArrayList paras = new ArrayList();
        dal.simpledatalist("select cid,nickname,name from accounts ", null, "cid", "name", sprlist, false, "", "");
        dal.simpledatalist("select cid,'抄送' name from accounts ", null, "cid", "name", spr2list, false, "", "");

        dal.RowsCount = 0;
        dal.ErrorMessage = "";
        string cid = Request.QueryString["cid"];
        string nodeid = Request.QueryString["nid"];
        paras.Clear();
        paras.Add(new SqlParameter("cid", cid));
        paras.Add(new SqlParameter("nodeid", nodeid));
        object rv = dal.GetDataSet("select AccountCid,nodeId,role from cc_flowNodeAccounts where projectCid=@cid and nodeId=@nodeid", paras);
        if (dal.RowsCount > 0)
        {
            DataTable dt = (rv as DataSet).Tables[0];
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                string accountid = dt.Rows[i]["AccountCid"].ToString();
                string role = dt.Rows[i]["role"].ToString();
                ListItem li = sprlist.Items.FindByValue(accountid);
                if (li!=null)
                {
                    li.Selected = true;
                    if(role=="抄送"){
                        spr2list.Items.FindByValue(accountid).Selected = true;
                    }
                }
            }
        }

        
     }

    protected void saveflow_Click(object sender, EventArgs e)
    {
        string cid = Request.QueryString["cid"];
        string nodeid = Request.QueryString["nid"];

        ArrayList paras = new ArrayList();
        paras.Clear();
        paras.Add(new SqlParameter("cid", cid));
        paras.Add(new SqlParameter("nodeid", nodeid));
        dal.RowsCount = 0;
        dal.ErrorMessage = "";
        dal.ExecDbScripts("delete cc_flowNodeAccounts where projectCid=@cid and nodeId=@nodeid", paras);
        for (int i = 0; i < sprlist.Items.Count; i++)
        {
            ListItem li = sprlist.Items[i];
            
            if (li.Selected==true)
            {
                paras.Clear();
                paras.Add(new SqlParameter("projectCid", cid));
                paras.Add(new SqlParameter("AccountCid", li.Value));
                paras.Add(new SqlParameter("nodeid", nodeid));
                paras.Add(new SqlParameter("role", (spr2list.Items[i].Selected==true?"抄送":"决策")  ));
                paras.Add(new SqlParameter("descript", li.Text));
                dal.RowsCount = 0;
                dal.ErrorMessage = "";
                dal.ExecDbScripts("insert into cc_flowNodeAccounts(projectCid,AccountCid,nodeId,role,descript) values(@projectCid,@AccountCid,@nodeid,@role,@descript) ", paras);
                Response.Write(dal.ErrorMessage);
            }
        }
        Alert(Form, "保存数据信息完成!");

    }

    protected void updflow_Click(object sender, EventArgs e)
    {

        ArrayList paras = new ArrayList();
        paras.Clear();
        paras.Add(new SqlParameter("cid", x_cid.Text));

    }

    protected void tooltab_SelectedIndexChanged(object sender, EventArgs e)
    {
        spr.Style["display"] = "none";
        sortnode.Style["display"] = "none";

        if (tooltab.SelectedValue == "0")
        {
            spr.Style["display"] = "";
        }else if (tooltab.SelectedValue == "1")
        {
            sortnode.Style["display"] = "";
        }
    }
    void SortRow(Object sender, EventArgs e)
    {
        Newtonsoft.Json.Linq.JObject jsonObj = Newtonsoft.Json.Linq.JObject.Parse(x_flowJSON.Text);

       
        string cid = Request.QueryString["cid"];


        ArrayList paras = new ArrayList();
        paras.Clear();
        paras.Add(new SqlParameter("cid", cid));
        dal.RowsCount = 0;
        dal.ErrorMessage = "";
        dal.ExecDbScripts("delete cc_flowNodes where projectCid=@cid ", paras);

        string[] la = sortstate1.Text.Split(',');
        int added = 0;
        for (int i = 0; i < la.GetLength(0); i++)
        {
            if (la[i] != "")
            {
                paras.Clear();
                paras.Add(new SqlParameter("projectCid", cid));
                paras.Add(new SqlParameter("parentNodeId",(i==0?cid:la[i-1])) );
                paras.Add(new SqlParameter("nodeId", la[i]));
                paras.Add(new SqlParameter("nodeName", jsonObj["nodes"][la[i]]["name"].ToString()));
                paras.Add(new SqlParameter("sortid", i+1));
                dal.RowsCount = 0;
                dal.ErrorMessage = "";
                dal.ExecDbScripts("insert into cc_flowNodes(projectCid,parentNodeId,nodeId,nodeName,sortid) values(@projectCid,@parentNodeId,@nodeId,@nodeName,@sortid) ", paras);
                if (dal.RowsCount > 0)
                {
                    added++;
                }
            }
        }
        paras.Clear();
        paras.Add(new SqlParameter("cid", cid));
        paras.Add(new SqlParameter("flowJSON", x_flowJSON.Text));
        paras.Add(new SqlParameter("nodeCount", added));
        dal.RowsCount = 0;
        dal.ErrorMessage = "";
        dal.ExecDbScripts("update cc_flow set flowJSON=@flowJSON,nodeCount=@nodeCount where cid=@cid ", paras);
        if (dal.RowsCount > 0)
        {
        }
        else
        {
            Alert(Form, "保存流程数据信息失败!");
            return;
        }
        Alert(Form,"保存排序信息完毕!");
    }
    public void Alert(Control updatePanel, string msg)
    {

        msg = msg.Replace("\r\n", "").Replace("'", "\\'");
        ScriptManager.RegisterClientScriptBlock(updatePanel, this.GetType(), "", "alert('" + msg + "')", true);
    }
</script>        

<!DOCTYPE html>
<html lang="cn" >
<head>
  <meta charset="UTF-8">
  <title></title>
</head>

<body style=" background-color:Gray">
  <form runat="server">
  <div style=" display:flex">
  <asp:RadioButtonList ID="tooltab" AutoPostBack="true"   Font-Names="微软雅黑" 
          RepeatDirection="Horizontal" runat="server" 
          onselectedindexchanged="tooltab_SelectedIndexChanged" >
          <asp:ListItem Value="0" Text="审批人" Selected="True"></asp:ListItem>
          <asp:ListItem Value="1" Text="节点排序" ></asp:ListItem>

  </asp:RadioButtonList>
  </div>
  <asp:Panel ID="spr" runat="server" Visible="true" BackColor="Silver"  >
  <div style=" display:flex">
      <asp:CheckBoxList ID="sprlist" runat="server" Height="100px" ForeColor="White" Width="134px">
      </asp:CheckBoxList>
      <asp:CheckBoxList ID="spr2list" runat="server" Height="100px" BackColor="Gray" ForeColor="Silver" Width="134px">
      </asp:CheckBoxList>

  <asp:Button ID="updflow"  Text="更新项目" style=" display:none" runat="server" onclick="updflow_Click" ></asp:Button>
  <asp:TextBox ID="x_cid" style=" display:none" ReadOnly="true" runat="server"></asp:TextBox>
  </div>
  <div style=" display:flex">
      <asp:Button ID="saveflow" style=" display:none1" Text="保存审批人" runat="server" onclick="saveflow_Click"></asp:Button>
  </div>
  </asp:Panel>

  <asp:Panel ID="sortnode" runat="server" Visible="true" style="display:none" BackColor="Silver">
  <table border="0" width="100%" cellspacing="0" cellpadding="0" id="table1">
		<tr>
			<td valign="top">
			<div align="center">
			<table border="0" width="94%" cellspacing="0" cellpadding="0" id="table2">
				<tr>
					<td align="left" valign="top">
					<asp:listbox id="funclist" ondblclick="SetValues(this)" 
                            style="border: 1px outset #6699FF; background-color: #FFFFFF;" Runat="server"
                            Height="328px" Width="405px" Font-Names="微软雅黑"/></td>
					<td>
					<p align="center">
					<input id="moveUp" onclick="moveSelected(document.getElementById('funclist'), false)" type=button style="font-family:微软雅黑;" value="上移"/></p>
					<p align="center">
					<input id="moveDown" onclick="moveSelected(document.getElementById('funclist'), true)" type=button style="font-family:微软雅黑;" value="下移"/></p>
					<p  align="center"><input id="moveDown0" onclick="sortfunc()" type="button" value="保存"  style="font-family:微软雅黑;"/></p></td>
				</tr>
			</table>
			</div>
			</td>
		</tr>
	</table>
  </asp:Panel>
<asp:TextBox ID="sortstate"  Text="" style="display:none" Runat=server/>
<asp:TextBox ID="sortstate1"  Text="" style="display:none" Runat="server"/>
<asp:Button ID="sortbtn" Text="sort" OnClick="SortRow" style="display:none" Runat="server"/>
  <asp:TextBox ID="x_flowJSON" Rows="10" style="display:none"  width="100%" TextMode="MultiLine" runat="server"></asp:TextBox>

  </form>
</body>
</html>
<script language="javascript" type="text/javascript">
    form = document.forms[0];
    function sortfunc() {
        if (!confirm('您确认保存排序结果吗?')) {
            return;
        }
        form.sortstate1.value = "";
        for (var i = 0; i < form.funclist.length; i++) {
            var _id = form.funclist.options[i].value;
            flowpanel.$nodeData[_id].sortid = i;
            form.sortstate1.value += _id + ",";
        }
        //  return;
        form.sortstate.value = "1";
        var obj = flowpanel.exportData();
        form.x_flowJSON.value = JSON.stringify(obj);
        form.sortbtn.click();
    }
    function AddListBoxOption(obj, _text, _value) {
        newOption = document.createElement("OPTION");
        newOption.text = _text;
        newOption.value = _value;
        obj.options.add(newOption);
    }
    function moveSelected(select, down) {

        if (select.selectedIndex != -1) {
            if (down) {
                if (select.selectedIndex != select.options.length - 1)
                    var i = select.selectedIndex + 1;
                else
                    return;
            }
            else {
                if (select.selectedIndex != 0)
                    var i = select.selectedIndex - 1;
                else
                    return;
            }
            var swapOption = new Object();
            swapOption.text = select.options[select.selectedIndex].text;
            swapOption.value = select.options[select.selectedIndex].value;
            swapOption.selected = select.options[select.selectedIndex].selected;
            //    swapOption.defaultSelected = select.options[select.selectedIndex].defaultSelected;
            for (var property in swapOption)
                select.options[select.selectedIndex][property] = select.options[i][property];
            for (var property in swapOption)
                select.options[i][property] = swapOption[property];
        }
    }
    function jsonSort(array, field, reverse) {
        //数组长度小于2 或 没有指定排序字段 或 不是json格式数据
        if (array.length < 2 || !field || typeof array[0] !== "object") return array;
        //数字类型排序
        if (typeof array[0][field] === "number") {
            array.sort(function (x, y) { return x[field] - y[field] });
        }
        //字符串类型排序
        if (typeof array[0][field] === "string") {
            array.sort(function (x, y) { return x[field].localeCompare(y[field]) });
        }
        //倒序
        if (reverse) {
            array.reverse();
        }
        return array;
    }
    var flowpanel = (window.parent.flowpanel);
    window.onload = function () {
        var obj = flowpanel.exportData();
        form.x_flowJSON.value = JSON.stringify(obj);

        var nodelist = document.getElementById('funclist');
        nodelist.length = 0;
        var sortid = 0;
        var obj2 = new Array();

        for (var i in obj.nodes) {
            flowpanel.$nodeData[i].id = i;
            obj2.push(flowpanel.$nodeData[i]);
        }
        var obj3 = jsonSort(obj2, 'sortid', false);
        for (var j = 0; j < obj3.length;j++ ) {
            flowpanel.$nodeData[obj3[j].id].sortid = sortid;
            AddListBoxOption(nodelist, obj3[j].name, obj3[j].id);
            sortid++;
        }
    }

</script>
运行结果演示

代码正常运行后如下图所示:

点击某一节点,点击控制栏最后的设置图标,会提供选择审批人的操作界面,如下图所示:

总结

关于 GooFlow 的引用,请下载我的资源:

https://download.csdn.net/download/michaelline/89601233

CosysJaneCommonAPI.CODAL 类的 dal.simpledatalist 方法需要在实际中自行改造,可参考我的文章:

《C# Web控件与数据感应之 ListControl 类》

CosysJaneCommonAPI.CODAL 类的 dal.GetDataSet 方法需要在实际中自行改造,可参考我的文章:

CosysJaneCommonAPI.CODAL 类的 dal.ExecDbScripts 方法需要在实际中自行改造,可参考我的文章:

《C#利用IDbCommand实现通用数据库脚本执行程序》

代码这里仅供大家参考,欢迎大家评论指教!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-08-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 关于 GooFlow
  • 功能需求
  • 范例运行环境
  • 设计数据表
    • 流程项目表
      • 流程项目节点明细表
        • 流程项目节点审批人表
          • 人员信息表
          • 示例代码
            • 流程图主功能
              • 设置审批人信息
                • 运行结果演示
                  • 总结
                  相关产品与服务
                  数据库
                  云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档