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

CSDN 2024-08-06 13:05:02 阅读 98

 

目录

关于 GooFlow

功能需求

范例运行环境

设计数据表

流程项目表

流程项目节点明细表

流程项目节点审批人表

 人员信息表

示例代码

流程图主功能

设置审批人信息

运行结果演示

总结


关于 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 修改时间

 创建脚本如下:

<code>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 修改时间

 创建脚本如下:

<code>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 修改时间

 创建脚本如下:

<code>

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) 昵称

 创建脚本如下:

<code>

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 代码,代码如下:

<%@ Page Language="C#" AutoEventWireup="true" MaintainScrollPositionOnPostback="true" ValidateRequest="FALSE" %>code>

<%@ Import Namespace="System.IO" %>code>

<%@ Import Namespace="System.Data" %>code>

<%@ Import Namespace="System.Data.SqlClient" %>code>

<script language="C#" runat="server">code>

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" >code>

<head>

<meta charset="UTF-8">code>

<title></title>

<link rel="stylesheet" href="dist/GooFlow.min.css?v=10" />code>

<link rel="stylesheet" href="fontawesome/css/font-awesome.min.css" />code>

</head>

<script src="dist/jquery.min.js"></script>code>

<script src="dist/GooFlow.js?v=7"></script>code>

<body>

<form runat="server">code>

<div style=" display:flex">code>

<asp:TextBox ID="x_flowname" placeholder="输入项目名称" runat="server"></asp:TextBox>code>

<asp:Button ID="saveflow" Text="创建项目" runat="server" onclick="saveflow_Click"></asp:Button>code>

<asp:Button ID="updflow" Text="更新项目" style=" display:none" runat="server" onclick="updflow_Click" ></asp:Button>code>

<asp:TextBox ID="x_cid" placeholder="cid" style="display:none" ReadOnly="true" runat="server"></asp:TextBox>code>

<asp:DropDownList ID="flowlist" runat="server" AutoPostBack="true"code>

onselectedindexchanged="flowlist_SelectedIndexChanged"></asp:DropDownList>code>

</div>

<div style=" margin:10px; display:flex">code>

<asp:Label ID="tip" Text="这是一些提示信息..." runat="server"></asp:Label>code>

</div>

<iframe id="tframe" width="500" height="400" style=" display:none;z-index:99;position:absolute;" runat="server"></iframe>code>

<div id="flowpanel" visible="false" runat="server">code>

</div>

<div>

<asp:TextBox ID="x_flowJSON" Rows="10" style="display:none" width="100%" TextMode="MultiLine" runat="server"></asp:TextBox>code>

</div>

</form>

</body>

</html>

<script language="javascript" type="text/javascript">code>

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'));code>

}

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 代码,代码如下:

<%@ Page Language="C#" AutoEventWireup="true" enableEventValidation="false" MaintainScrollPositionOnPostback="true" ValidateRequest="FALSE" %>code>

<%@ Import Namespace="System.IO" %>code>

<%@ Import Namespace="System.Data" %>code>

<%@ Import Namespace="System.Data.SqlClient" %>code>

<script language="C#" runat="server">code>

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" >code>

<head>

<meta charset="UTF-8">code>

<title></title>

</head>

<body style=" background-color:Gray">code>

<form runat="server">code>

<div style=" display:flex">code>

<asp:RadioButtonList ID="tooltab" AutoPostBack="true" Font-Names="微软雅黑" code>

RepeatDirection="Horizontal" runat="server" code>

onselectedindexchanged="tooltab_SelectedIndexChanged" >code>

<asp:ListItem Value="0" Text="审批人" Selected="True"></asp:ListItem>code>

<asp:ListItem Value="1" Text="节点排序" ></asp:ListItem>code>

</asp:RadioButtonList>

</div>

<asp:Panel ID="spr" runat="server" Visible="true" BackColor="Silver" >code>

<div style=" display:flex">code>

<asp:CheckBoxList ID="sprlist" runat="server" Height="100px" ForeColor="White" Width="134px">code>

</asp:CheckBoxList>

<asp:CheckBoxList ID="spr2list" runat="server" Height="100px" BackColor="Gray" ForeColor="Silver" Width="134px">code>

</asp:CheckBoxList>

<asp:Button ID="updflow" Text="更新项目" style=" display:none" runat="server" onclick="updflow_Click" ></asp:Button>code>

<asp:TextBox ID="x_cid" style=" display:none" ReadOnly="true" runat="server"></asp:TextBox>code>

</div>

<div style=" display:flex">code>

<asp:Button ID="saveflow" style=" display:none1" Text="保存审批人" runat="server" onclick="saveflow_Click"></asp:Button>code>

</div>

</asp:Panel>

<asp:Panel ID="sortnode" runat="server" Visible="true" style="display:none" BackColor="Silver">code>

<table border="0" width="100%" cellspacing="0" cellpadding="0" id="table1">code>

<tr>

<td valign="top">code>

<div align="center">code>

<table border="0" width="94%" cellspacing="0" cellpadding="0" id="table2">code>

<tr>

<td align="left" valign="top">code>

<asp:listbox id="funclist" ondblclick="SetValues(this)" code>

style="border: 1px outset #6699FF; background-color: #FFFFFF;" Runat="server"code>

Height="328px" Width="405px" Font-Names="微软雅黑"/></td>code>

<td>

<p align="center">code>

<input id="moveUp" onclick="moveSelected(document.getElementById('funclist'), false)" type=button style="font-family:微软雅黑;" value="上移"/></p>code>

<p align="center">code>

<input id="moveDown" onclick="moveSelected(document.getElementById('funclist'), true)" type=button style="font-family:微软雅黑;" value="下移"/></p>code>

<p align="center"><input id="moveDown0" onclick="sortfunc()" type="button" value="保存" style="font-family:微软雅黑;"/></p></td>code>

</tr>

</table>

</div>

</td>

</tr>

</table>

</asp:Panel>

<asp:TextBox ID="sortstate" Text="" style="display:none" Runat=server/>code>

<asp:TextBox ID="sortstate1" Text="" style="display:none" Runat="server"/>code>

<asp:Button ID="sortbtn" Text="sort" OnClick="SortRow" style="display:none" Runat="server"/>code>

<asp:TextBox ID="x_flowJSON" Rows="10" style="display:none" width="100%" TextMode="MultiLine" runat="server"></asp:TextBox>code>

</form>

</body>

</html>

<script language="javascript" type="text/javascript">code>

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实现通用数据库脚本执行程序》

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



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。