当前位置:   article > 正文

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

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

 

目录

关于 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 表记录项目信息,主要说明见下表:

序号字段名类型说明
1ciduniqueidentifier记录唯一标识
2flowNamenvarchar(50)流程项目名称
3nodeCountint节点总个数
4desriptnvarchar(50)项目描述
5flowJSONnvarchar(MAX)流程全部 JSON 数据
6sys_insusernvarchar(100)创建信息用户名
7sys_instimedatetime创建时间
8sys_updusernvarchar(100)最后修改信息用户名
9sys_updtimedatetime修改时间

 创建脚本如下:

  1. CREATE TABLE [dbo].[cc_flow](
  2. [cid] [uniqueidentifier] ROWGUIDCOL NOT NULL,
  3. [flowName] [nvarchar](50) NOT NULL,
  4. [nodeCount] [int] NULL,
  5. [desript] [nvarchar](100) NULL,
  6. [flowJSON] [nvarchar](max) NULL,
  7. [sys_insuser] [nvarchar](100) NULL,
  8. [sys_instime] [datetime] NULL,
  9. [sys_upduser] [nvarchar](100) NULL,
  10. [sys_updtime] [datetime] NULL,
  11. CONSTRAINT [PK_cc_flow] PRIMARY KEY CLUSTERED
  12. (
  13. [cid] ASC
  14. )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
  15. CONSTRAINT [IX_cc_flow] UNIQUE NONCLUSTERED
  16. (
  17. [flowName] ASC
  18. )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  19. ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
  20. GO
  21. ALTER TABLE [dbo].[cc_flow] ADD CONSTRAINT [DF_cc_flow_cid] DEFAULT (newid()) FOR [cid]
  22. GO

流程项目节点明细表

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

序号字段名类型说明
1ciduniqueidentifier记录唯一标识
2nodeIdnvarchar(50)节点ID
3nodeNamenvarchar(50)节点流程名称
4desriptnvarchar(100)节点流程描述
5parentNodeIdnvarchar(50)父节点ID
6projectCiduniqueidentifier流程项目ID,所属的项目唯一标识
7sortidint节点排序
8sys_insusernvarchar(100)创建信息用户名
9sys_instimedatetime创建时间
10sys_updusernvarchar(100)最后修改信息用户名
11sys_updtimedatetime修改时间

 创建脚本如下:

  1. CREATE TABLE [dbo].[cc_flowNodes](
  2. [cid] [uniqueidentifier] NOT NULL,
  3. [nodeId] [nvarchar](50) NOT NULL,
  4. [nodeName] [nvarchar](50) NOT NULL,
  5. [desript] [nvarchar](100) NULL,
  6. [parentNodeId] [nvarchar](50) NULL,
  7. [projectCid] [uniqueidentifier] NOT NULL,
  8. [sortid] [int] NULL,
  9. [sys_insuser] [nvarchar](100) NULL,
  10. [sys_instime] [datetime] NULL,
  11. [sys_upduser] [nvarchar](100) NULL,
  12. [sys_updtime] [datetime] NULL
  13. ) ON [PRIMARY]
  14. GO
  15. ALTER TABLE [dbo].[cc_flowNodes] ADD CONSTRAINT [DF_cc_flowNodes_cid] DEFAULT (newid()) FOR [cid]
  16. GO
流程项目节点审批人表

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

序号字段名类型说明
1ciduniqueidentifier记录唯一标识
2nodeIdnvarchar(50)节点ID
3AccountCiduniqueidentifier所属的人员信息ID
4desriptnvarchar(100)描述,可以记录诸如姓名相关的一些信息
5rolenvarchar(50)审批人权限(如决策、抄送)
6projectCiduniqueidentifier流程项目ID,所属的项目唯一标识
7sys_insusernvarchar(100)创建信息用户名
8sys_instimedatetime创建时间
9sys_updusernvarchar(100)最后修改信息用户名
10sys_updtimedatetime修改时间

 创建脚本如下:

  1. CREATE TABLE [dbo].[cc_flowNodeAccounts](
  2. [cid] [uniqueidentifier] NOT NULL,
  3. [projectCid] [uniqueidentifier] NOT NULL,
  4. [AccountCid] [uniqueidentifier] NOT NULL,
  5. [descript] [nvarchar](100) NULL,
  6. [nodeId] [nvarchar](50) NOT NULL,
  7. [role] [nvarchar](50) NULL,
  8. [sys_insuser] [nvarchar](100) NULL,
  9. [sys_instime] [datetime] NULL,
  10. [sys_upduser] [nvarchar](100) NULL,
  11. [sys_updtime] [datetime] NULL
  12. ) ON [PRIMARY]
  13. GO
  14. ALTER TABLE [dbo].[cc_flowNodeAccounts] ADD CONSTRAINT [DF_cc_flowNodeBuss_cid] DEFAULT (newid()) FOR [cid]
  15. GO
 人员信息表

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

序号字段名类型说明
1ciduniqueidentifier记录唯一标识
2namenvarchar(50)姓名
3nickNamenvarchar(50)昵称

 创建脚本如下:

  1. CREATE TABLE [dbo].[accounts](
  2. [cid] [uniqueidentifier] ROWGUIDCOL NOT NULL,
  3. [name] [nvarchar](50) NULL,
  4. [nickname] [nvarchar](500) NULL,
  5. CONSTRAINT [PK_wxmp_accounts] PRIMARY KEY CLUSTERED
  6. (
  7. [cid] ASC
  8. )
  9. )
  10. GO
  11. ALTER TABLE [dbo].[accounts] ADD CONSTRAINT [DF_wxmp_accounts_cid] DEFAULT (newid()) FOR [cid]
  12. GO

示例代码

流程图主功能

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

  1. <%@ Page Language="C#" AutoEventWireup="true" MaintainScrollPositionOnPostback="true" ValidateRequest="FALSE" %>
  2. <%@ Import Namespace="System.IO" %>
  3. <%@ Import Namespace="System.Data" %>
  4. <%@ Import Namespace="System.Data.SqlClient" %>
  5. <script language="C#" runat="server">
  6. public CosysJaneCommonAPI.CODAL dal = new CosysJaneCommonAPI.CODAL();
  7. public DateTime dt = DateTime.Now;
  8. void Page_load(Object sender, EventArgs e)
  9. {
  10. dal.RunAt = Form;
  11. if (Page.IsPostBack == true) return;
  12. dal.ConnKeyString = "JaneConnectionCloud";
  13. ArrayList paras = new ArrayList();
  14. paras.Clear();
  15. paras.Add(new SqlParameter("a", "2"));
  16. dal.simpledatalist("select cid,flowName from cc_flow order by flowName ", paras, "cid", "flowName",flowlist, true, "", "选择打开已创建流程");
  17. }
  18. protected void saveflow_Click(object sender, EventArgs e)
  19. {
  20. dal.ConnKeyString = "JaneConnectionCloud";
  21. ArrayList paras = new ArrayList();
  22. paras.Clear();
  23. paras.Add(new SqlParameter("flowname", x_flowname.Text));
  24. dal.RowsCount = 0;
  25. dal.ErrorMessage = "";
  26. dal.ExecDbScripts("insert into cc_flow (flowName) values(@flowname) ", paras);
  27. if (dal.RowsCount > 0)
  28. {
  29. tip.Text = "创建成功!";
  30. flowpanel.Visible = true;
  31. }else
  32. {
  33. if (dal.ErrorMessage.IndexOf("重复键") != -1)
  34. {
  35. dal.RowsCount = 0;
  36. dal.ErrorMessage = "";
  37. paras.Clear();
  38. paras.Add(new SqlParameter("flowname", x_flowname.Text));
  39. object rv = dal.GetDataSet("select * from cc_flow where flowname=@flowname ", paras);
  40. if (dal.RowsCount > 0)
  41. {
  42. DataSet ds = rv as DataSet;
  43. DataTable dt = ds.Tables[0];
  44. x_cid.Text = dt.Rows[0]["cid"].ToString();
  45. x_flowJSON.Text = dt.Rows[0]["flowJSON"].ToString();
  46. tip.Text = "打开成功!";
  47. flowpanel.Visible = true;
  48. }
  49. else
  50. {
  51. tip.Text = dal.ErrorMessage;
  52. flowpanel.Visible = false;
  53. }
  54. }
  55. else
  56. {
  57. tip.Text = dal.ErrorMessage;
  58. flowpanel.Visible = false;
  59. }
  60. }
  61. }
  62. protected void updflow_Click(object sender, EventArgs e)
  63. {
  64. dal.ConnKeyString = "JaneConnectionCloud";
  65. ArrayList paras = new ArrayList();
  66. Newtonsoft.Json.Linq.JObject jsonObj = Newtonsoft.Json.Linq.JObject.Parse(x_flowJSON.Text);
  67. string nodelist = "";
  68. foreach (Newtonsoft.Json.Linq.JProperty jt in jsonObj["nodes"])
  69. {
  70. nodelist+=jt.Name+",";
  71. }
  72. string cid = x_cid.Text;
  73. dal.ConnKeyString = "JaneConnectionCloud";
  74. paras.Clear();
  75. paras.Add(new SqlParameter("cid", cid));
  76. dal.RowsCount = 0;
  77. dal.ErrorMessage = "";
  78. dal.ExecDbScripts("delete cc_flowNodes where projectCid=@cid ", paras);
  79. string[] la = nodelist.Split(',');
  80. int added = 0;
  81. for (int i = 0; i < la.GetLength(0); i++)
  82. {
  83. if (la[i] != "")
  84. {
  85. paras.Clear();
  86. paras.Add(new SqlParameter("projectCid", cid));
  87. paras.Add(new SqlParameter("parentNodeId", (i == 0 ? cid : la[i - 1])));
  88. paras.Add(new SqlParameter("nodeId", la[i]));
  89. paras.Add(new SqlParameter("nodeName", jsonObj["nodes"][la[i]]["name"].ToString()));
  90. paras.Add(new SqlParameter("sortid", i + 1));
  91. dal.RowsCount = 0;
  92. dal.ErrorMessage = "";
  93. dal.ExecDbScripts("insert into cc_flowNodes(projectCid,parentNodeId,nodeId,nodeName,sortid) values(@projectCid,@parentNodeId,@nodeId,@nodeName,@sortid) ", paras);
  94. if (dal.RowsCount > 0)
  95. {
  96. added++;
  97. }
  98. }
  99. }
  100. paras.Clear();
  101. paras.Add(new SqlParameter("cid", x_cid.Text));
  102. paras.Add(new SqlParameter("flowName",x_flowname.Text));
  103. paras.Add(new SqlParameter("flowJSON", x_flowJSON.Text));
  104. dal.RowsCount = 0;
  105. dal.ErrorMessage = "";
  106. dal.ExecDbScripts("update cc_flow set flowName=@flowname,flowJSON=@flowJSON where cid=@cid ", paras);
  107. if (dal.RowsCount > 0)
  108. {
  109. tip.Text = "更新成功!";
  110. }
  111. else
  112. {
  113. tip.Text = dal.ErrorMessage;
  114. }
  115. }
  116. protected void flowlist_SelectedIndexChanged(object sender, EventArgs e)
  117. {
  118. if (flowlist.SelectedValue == "")
  119. {
  120. return;
  121. }
  122. dal.ConnKeyString = "JaneConnectionCloud";
  123. ArrayList paras = new ArrayList();
  124. dal.RowsCount = 0;
  125. dal.ErrorMessage = "";
  126. paras.Clear();
  127. paras.Add(new SqlParameter("cid",flowlist.SelectedValue));
  128. object rv = dal.GetDataSet("select * from cc_flow where cid=@cid ", paras);
  129. if (dal.RowsCount > 0)
  130. {
  131. DataSet ds = rv as DataSet;
  132. DataTable dt = ds.Tables[0];
  133. x_cid.Text = dt.Rows[0]["cid"].ToString();
  134. x_flowname.Text = dt.Rows[0]["flowName"].ToString();
  135. x_flowJSON.Text = dt.Rows[0]["flowJSON"].ToString();
  136. tip.Text = "打开成功!";
  137. flowpanel.Visible = true;
  138. }
  139. else
  140. {
  141. tip.Text = dal.ErrorMessage;
  142. flowpanel.Visible = false;
  143. }
  144. }
  145. </script>
  146. <!DOCTYPE html>
  147. <html lang="cn" >
  148. <head>
  149. <meta charset="UTF-8">
  150. <title></title>
  151. <link rel="stylesheet" href="dist/GooFlow.min.css?v=10" />
  152. <link rel="stylesheet" href="fontawesome/css/font-awesome.min.css" />
  153. </head>
  154. <script src="dist/jquery.min.js"></script>
  155. <script src="dist/GooFlow.js?v=7"></script>
  156. <body>
  157. <form runat="server">
  158. <div style=" display:flex">
  159. <asp:TextBox ID="x_flowname" placeholder="输入项目名称" runat="server"></asp:TextBox>
  160. <asp:Button ID="saveflow" Text="创建项目" runat="server" onclick="saveflow_Click"></asp:Button>
  161. <asp:Button ID="updflow" Text="更新项目" style=" display:none" runat="server" onclick="updflow_Click" ></asp:Button>
  162. <asp:TextBox ID="x_cid" placeholder="cid" style="display:none" ReadOnly="true" runat="server"></asp:TextBox>
  163. <asp:DropDownList ID="flowlist" runat="server" AutoPostBack="true"
  164. onselectedindexchanged="flowlist_SelectedIndexChanged"></asp:DropDownList>
  165. </div>
  166. <div style=" margin:10px; display:flex">
  167. <asp:Label ID="tip" Text="这是一些提示信息..." runat="server"></asp:Label>
  168. </div>
  169. <iframe id="tframe" width="500" height="400" style=" display:none;z-index:99;position:absolute;" runat="server"></iframe>
  170. <div id="flowpanel" visible="false" runat="server">
  171. </div>
  172. <div>
  173. <asp:TextBox ID="x_flowJSON" Rows="10" style="display:none" width="100%" TextMode="MultiLine" runat="server"></asp:TextBox>
  174. </div>
  175. </form>
  176. </body>
  177. </html>
  178. <script language="javascript" type="text/javascript">
  179. var tframe=$('#tframe');
  180. var curnode=null;
  181. var flowpanel=null;
  182. var sortBy = function (filed, rev, primer) {
  183. rev = (rev) ? -1 : 1;
  184. return function (a, b) {
  185. a = a[filed];
  186. b = b[filed];
  187. if (primer && typeof (primer) != 'undefined') {
  188. a = primer(a);
  189. b = primer(b);
  190. }else{
  191. if(!isNaN(a) && !isNaN(a)){
  192. a = Number(a);
  193. b = Number(b);
  194. }
  195. }
  196. if (a < b) { return rev * -1; }
  197. if (a > b) { return rev * 1; }
  198. return 1;
  199. }
  200. };
  201. $(function(){
  202. var options={initLabelText:"未命名",toolBtns:["task","chat","state"],toolBtnRemarks:{cursor:"选择指针",direct:"连线",task:"任务结点",chat:"决策结点",state:"状态结点",group:"组织区域框"},headBtns:["save","undo","redo","new","expand"],headBtnRemarks:['保存','撤销','重做','清空画布','结点设置']};
  203. flowpanel = $('#flowpanel').createGooFlow(options);
  204. var flowpanelData = {
  205. areas: {
  206. flowpanel_area_17: {
  207. color: "yellow",
  208. height: 300,
  209. left: 40,
  210. name: "部门一",
  211. top: 30,
  212. width: 150,
  213. },
  214. flowpanel_area_18: {
  215. color: "blue",
  216. height: 300,
  217. left: 200,
  218. name: "部门二",
  219. top: 30,
  220. width: 150,
  221. },
  222. flowpanel_area_19: {
  223. color: "green",
  224. height: 300,
  225. left: 360,
  226. name: "部门三",
  227. top: 30,
  228. width: 150,
  229. },
  230. flowpanel_area_20: {
  231. color: "red",
  232. height: 300,
  233. left: 520,
  234. name: "部门四",
  235. top: 30,
  236. width: 150,
  237. },
  238. },
  239. lines: {
  240. flowpanel_line_11: {
  241. from: "flowpanel_node_1",
  242. marked: false,
  243. name: "",
  244. to: "flowpanel_node_2",
  245. type: "sl",
  246. },
  247. },
  248. nodes: {
  249. flowpanel_node_1: {
  250. height: 24,
  251. left: 70,
  252. name: "节点流程1",
  253. top: 66,
  254. type: "chat",
  255. width: 86,
  256. sortid:1,
  257. id:"flowpanel_node_1",
  258. },
  259. flowpanel_node_2: {
  260. height: 24,
  261. left: 240,
  262. name: "节点流程2",
  263. top: 132,
  264. type: "state",
  265. width: 86,
  266. sortid:2,
  267. id:"flowpanel_node_2",
  268. },
  269. }
  270. };
  271. flowpanel.loadData(flowpanelData);
  272. if($('#x_flowJSON').val()!=""){
  273. flowpanel.clearData();
  274. flowpanel.loadData($.parseJSON($('#x_flowJSON').val()));
  275. alert("加载流程图成功");
  276. }
  277. flowpanel.setTitle($('#x_flowname').val());
  278. $('#flowpanel').css('backgroundColor','silver');
  279. $('#flowpanel').css('borderColor','silver');
  280. var obj = flowpanel.exportData();
  281. flowpanel.onExpandClick=function(){
  282. if(curnode==null) return;
  283. var x=(curnode.offset().left+parseInt(curnode.css('width'),10))+'px';
  284. var y=curnode.offset().top+'px';
  285. tframe.css('left',x);
  286. tframe.css('top',y);
  287. tframe.attr('src','test_server.aspx?cid='+$('#x_cid').val()+'&nid='+curnode.selector.substring(1));
  288. tframe.css('display',(tframe.css('display')=='none'?'':'none'));
  289. }
  290. flowpanel.onBtnSaveClick=function(){
  291. $('#x_flowJSON').val(JSON.stringify(this.exportData()));
  292. $('#updflow').click();
  293. }
  294. flowpanel.onItemFocus=function(id,type){
  295. flowpanel.focusItem(id,false);
  296. curnode=$("#"+id);
  297. tframe.css('display','none');
  298. }
  299. });
  300. </script>
设置审批人信息

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

  1. <%@ Page Language="C#" AutoEventWireup="true" enableEventValidation="false" MaintainScrollPositionOnPostback="true" ValidateRequest="FALSE" %>
  2. <%@ Import Namespace="System.IO" %>
  3. <%@ Import Namespace="System.Data" %>
  4. <%@ Import Namespace="System.Data.SqlClient" %>
  5. <script language="C#" runat="server">
  6. public CosysJaneCommonAPI.CODAL dal = new CosysJaneCommonAPI.CODAL();
  7. public DateTime dt = DateTime.Now;
  8. void Page_load(Object sender, EventArgs e)
  9. {
  10. dal.RunAt = Form;
  11. if (Page.IsPostBack == true) return;
  12. ArrayList paras = new ArrayList();
  13. dal.simpledatalist("select cid,nickname,name from accounts ", null, "cid", "name", sprlist, false, "", "");
  14. dal.simpledatalist("select cid,'抄送' name from accounts ", null, "cid", "name", spr2list, false, "", "");
  15. dal.RowsCount = 0;
  16. dal.ErrorMessage = "";
  17. string cid = Request.QueryString["cid"];
  18. string nodeid = Request.QueryString["nid"];
  19. paras.Clear();
  20. paras.Add(new SqlParameter("cid", cid));
  21. paras.Add(new SqlParameter("nodeid", nodeid));
  22. object rv = dal.GetDataSet("select AccountCid,nodeId,role from cc_flowNodeAccounts where projectCid=@cid and nodeId=@nodeid", paras);
  23. if (dal.RowsCount > 0)
  24. {
  25. DataTable dt = (rv as DataSet).Tables[0];
  26. for (int i = 0; i < dt.Rows.Count; i++)
  27. {
  28. string accountid = dt.Rows[i]["AccountCid"].ToString();
  29. string role = dt.Rows[i]["role"].ToString();
  30. ListItem li = sprlist.Items.FindByValue(accountid);
  31. if (li!=null)
  32. {
  33. li.Selected = true;
  34. if(role=="抄送"){
  35. spr2list.Items.FindByValue(accountid).Selected = true;
  36. }
  37. }
  38. }
  39. }
  40. }
  41. protected void saveflow_Click(object sender, EventArgs e)
  42. {
  43. string cid = Request.QueryString["cid"];
  44. string nodeid = Request.QueryString["nid"];
  45. ArrayList paras = new ArrayList();
  46. paras.Clear();
  47. paras.Add(new SqlParameter("cid", cid));
  48. paras.Add(new SqlParameter("nodeid", nodeid));
  49. dal.RowsCount = 0;
  50. dal.ErrorMessage = "";
  51. dal.ExecDbScripts("delete cc_flowNodeAccounts where projectCid=@cid and nodeId=@nodeid", paras);
  52. for (int i = 0; i < sprlist.Items.Count; i++)
  53. {
  54. ListItem li = sprlist.Items[i];
  55. if (li.Selected==true)
  56. {
  57. paras.Clear();
  58. paras.Add(new SqlParameter("projectCid", cid));
  59. paras.Add(new SqlParameter("AccountCid", li.Value));
  60. paras.Add(new SqlParameter("nodeid", nodeid));
  61. paras.Add(new SqlParameter("role", (spr2list.Items[i].Selected==true?"抄送":"决策") ));
  62. paras.Add(new SqlParameter("descript", li.Text));
  63. dal.RowsCount = 0;
  64. dal.ErrorMessage = "";
  65. dal.ExecDbScripts("insert into cc_flowNodeAccounts(projectCid,AccountCid,nodeId,role,descript) values(@projectCid,@AccountCid,@nodeid,@role,@descript) ", paras);
  66. Response.Write(dal.ErrorMessage);
  67. }
  68. }
  69. Alert(Form, "保存数据信息完成!");
  70. }
  71. protected void updflow_Click(object sender, EventArgs e)
  72. {
  73. ArrayList paras = new ArrayList();
  74. paras.Clear();
  75. paras.Add(new SqlParameter("cid", x_cid.Text));
  76. }
  77. protected void tooltab_SelectedIndexChanged(object sender, EventArgs e)
  78. {
  79. spr.Style["display"] = "none";
  80. sortnode.Style["display"] = "none";
  81. if (tooltab.SelectedValue == "0")
  82. {
  83. spr.Style["display"] = "";
  84. }else if (tooltab.SelectedValue == "1")
  85. {
  86. sortnode.Style["display"] = "";
  87. }
  88. }
  89. void SortRow(Object sender, EventArgs e)
  90. {
  91. Newtonsoft.Json.Linq.JObject jsonObj = Newtonsoft.Json.Linq.JObject.Parse(x_flowJSON.Text);
  92. string cid = Request.QueryString["cid"];
  93. ArrayList paras = new ArrayList();
  94. paras.Clear();
  95. paras.Add(new SqlParameter("cid", cid));
  96. dal.RowsCount = 0;
  97. dal.ErrorMessage = "";
  98. dal.ExecDbScripts("delete cc_flowNodes where projectCid=@cid ", paras);
  99. string[] la = sortstate1.Text.Split(',');
  100. int added = 0;
  101. for (int i = 0; i < la.GetLength(0); i++)
  102. {
  103. if (la[i] != "")
  104. {
  105. paras.Clear();
  106. paras.Add(new SqlParameter("projectCid", cid));
  107. paras.Add(new SqlParameter("parentNodeId",(i==0?cid:la[i-1])) );
  108. paras.Add(new SqlParameter("nodeId", la[i]));
  109. paras.Add(new SqlParameter("nodeName", jsonObj["nodes"][la[i]]["name"].ToString()));
  110. paras.Add(new SqlParameter("sortid", i+1));
  111. dal.RowsCount = 0;
  112. dal.ErrorMessage = "";
  113. dal.ExecDbScripts("insert into cc_flowNodes(projectCid,parentNodeId,nodeId,nodeName,sortid) values(@projectCid,@parentNodeId,@nodeId,@nodeName,@sortid) ", paras);
  114. if (dal.RowsCount > 0)
  115. {
  116. added++;
  117. }
  118. }
  119. }
  120. paras.Clear();
  121. paras.Add(new SqlParameter("cid", cid));
  122. paras.Add(new SqlParameter("flowJSON", x_flowJSON.Text));
  123. paras.Add(new SqlParameter("nodeCount", added));
  124. dal.RowsCount = 0;
  125. dal.ErrorMessage = "";
  126. dal.ExecDbScripts("update cc_flow set flowJSON=@flowJSON,nodeCount=@nodeCount where cid=@cid ", paras);
  127. if (dal.RowsCount > 0)
  128. {
  129. }
  130. else
  131. {
  132. Alert(Form, "保存流程数据信息失败!");
  133. return;
  134. }
  135. Alert(Form,"保存排序信息完毕!");
  136. }
  137. public void Alert(Control updatePanel, string msg)
  138. {
  139. msg = msg.Replace("\r\n", "").Replace("'", "\\'");
  140. ScriptManager.RegisterClientScriptBlock(updatePanel, this.GetType(), "", "alert('" + msg + "')", true);
  141. }
  142. </script>
  143. <!DOCTYPE html>
  144. <html lang="cn" >
  145. <head>
  146. <meta charset="UTF-8">
  147. <title></title>
  148. </head>
  149. <body style=" background-color:Gray">
  150. <form runat="server">
  151. <div style=" display:flex">
  152. <asp:RadioButtonList ID="tooltab" AutoPostBack="true" Font-Names="微软雅黑"
  153. RepeatDirection="Horizontal" runat="server"
  154. onselectedindexchanged="tooltab_SelectedIndexChanged" >
  155. <asp:ListItem Value="0" Text="审批人" Selected="True"></asp:ListItem>
  156. <asp:ListItem Value="1" Text="节点排序" ></asp:ListItem>
  157. </asp:RadioButtonList>
  158. </div>
  159. <asp:Panel ID="spr" runat="server" Visible="true" BackColor="Silver" >
  160. <div style=" display:flex">
  161. <asp:CheckBoxList ID="sprlist" runat="server" Height="100px" ForeColor="White" Width="134px">
  162. </asp:CheckBoxList>
  163. <asp:CheckBoxList ID="spr2list" runat="server" Height="100px" BackColor="Gray" ForeColor="Silver" Width="134px">
  164. </asp:CheckBoxList>
  165. <asp:Button ID="updflow" Text="更新项目" style=" display:none" runat="server" onclick="updflow_Click" ></asp:Button>
  166. <asp:TextBox ID="x_cid" style=" display:none" ReadOnly="true" runat="server"></asp:TextBox>
  167. </div>
  168. <div style=" display:flex">
  169. <asp:Button ID="saveflow" style=" display:none1" Text="保存审批人" runat="server" onclick="saveflow_Click"></asp:Button>
  170. </div>
  171. </asp:Panel>
  172. <asp:Panel ID="sortnode" runat="server" Visible="true" style="display:none" BackColor="Silver">
  173. <table border="0" width="100%" cellspacing="0" cellpadding="0" id="table1">
  174. <tr>
  175. <td valign="top">
  176. <div align="center">
  177. <table border="0" width="94%" cellspacing="0" cellpadding="0" id="table2">
  178. <tr>
  179. <td align="left" valign="top">
  180. <asp:listbox id="funclist" ondblclick="SetValues(this)"
  181. style="border: 1px outset #6699FF; background-color: #FFFFFF;" Runat="server"
  182. Height="328px" Width="405px" Font-Names="微软雅黑"/></td>
  183. <td>
  184. <p align="center">
  185. <input id="moveUp" onclick="moveSelected(document.getElementById('funclist'), false)" type=button style="font-family:微软雅黑;" value="上移"/></p>
  186. <p align="center">
  187. <input id="moveDown" onclick="moveSelected(document.getElementById('funclist'), true)" type=button style="font-family:微软雅黑;" value="下移"/></p>
  188. <p align="center"><input id="moveDown0" onclick="sortfunc()" type="button" value="保存" style="font-family:微软雅黑;"/></p></td>
  189. </tr>
  190. </table>
  191. </div>
  192. </td>
  193. </tr>
  194. </table>
  195. </asp:Panel>
  196. <asp:TextBox ID="sortstate" Text="" style="display:none" Runat=server/>
  197. <asp:TextBox ID="sortstate1" Text="" style="display:none" Runat="server"/>
  198. <asp:Button ID="sortbtn" Text="sort" OnClick="SortRow" style="display:none" Runat="server"/>
  199. <asp:TextBox ID="x_flowJSON" Rows="10" style="display:none" width="100%" TextMode="MultiLine" runat="server"></asp:TextBox>
  200. </form>
  201. </body>
  202. </html>
  203. <script language="javascript" type="text/javascript">
  204. form = document.forms[0];
  205. function sortfunc() {
  206. if (!confirm('您确认保存排序结果吗?')) {
  207. return;
  208. }
  209. form.sortstate1.value = "";
  210. for (var i = 0; i < form.funclist.length; i++) {
  211. var _id = form.funclist.options[i].value;
  212. flowpanel.$nodeData[_id].sortid = i;
  213. form.sortstate1.value += _id + ",";
  214. }
  215. // return;
  216. form.sortstate.value = "1";
  217. var obj = flowpanel.exportData();
  218. form.x_flowJSON.value = JSON.stringify(obj);
  219. form.sortbtn.click();
  220. }
  221. function AddListBoxOption(obj, _text, _value) {
  222. newOption = document.createElement("OPTION");
  223. newOption.text = _text;
  224. newOption.value = _value;
  225. obj.options.add(newOption);
  226. }
  227. function moveSelected(select, down) {
  228. if (select.selectedIndex != -1) {
  229. if (down) {
  230. if (select.selectedIndex != select.options.length - 1)
  231. var i = select.selectedIndex + 1;
  232. else
  233. return;
  234. }
  235. else {
  236. if (select.selectedIndex != 0)
  237. var i = select.selectedIndex - 1;
  238. else
  239. return;
  240. }
  241. var swapOption = new Object();
  242. swapOption.text = select.options[select.selectedIndex].text;
  243. swapOption.value = select.options[select.selectedIndex].value;
  244. swapOption.selected = select.options[select.selectedIndex].selected;
  245. // swapOption.defaultSelected = select.options[select.selectedIndex].defaultSelected;
  246. for (var property in swapOption)
  247. select.options[select.selectedIndex][property] = select.options[i][property];
  248. for (var property in swapOption)
  249. select.options[i][property] = swapOption[property];
  250. }
  251. }
  252. function jsonSort(array, field, reverse) {
  253. //数组长度小于2 或 没有指定排序字段 或 不是json格式数据
  254. if (array.length < 2 || !field || typeof array[0] !== "object") return array;
  255. //数字类型排序
  256. if (typeof array[0][field] === "number") {
  257. array.sort(function (x, y) { return x[field] - y[field] });
  258. }
  259. //字符串类型排序
  260. if (typeof array[0][field] === "string") {
  261. array.sort(function (x, y) { return x[field].localeCompare(y[field]) });
  262. }
  263. //倒序
  264. if (reverse) {
  265. array.reverse();
  266. }
  267. return array;
  268. }
  269. var flowpanel = (window.parent.flowpanel);
  270. window.onload = function () {
  271. var obj = flowpanel.exportData();
  272. form.x_flowJSON.value = JSON.stringify(obj);
  273. var nodelist = document.getElementById('funclist');
  274. nodelist.length = 0;
  275. var sortid = 0;
  276. var obj2 = new Array();
  277. for (var i in obj.nodes) {
  278. flowpanel.$nodeData[i].id = i;
  279. obj2.push(flowpanel.$nodeData[i]);
  280. }
  281. var obj3 = jsonSort(obj2, 'sortid', false);
  282. for (var j = 0; j < obj3.length;j++ ) {
  283. flowpanel.$nodeData[obj3[j].id].sortid = sortid;
  284. AddListBoxOption(nodelist, obj3[j].name, obj3[j].id);
  285. sortid++;
  286. }
  287. }
  288. </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实现通用数据库脚本执行程序》

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/码创造者/article/detail/1008999
推荐阅读
相关标签
  

闽ICP备14008679号