工作流(2):工作流流程图设计
创始人
2025-05-31 20:32:59
0

接上篇:

工作流(1):表格设计_斯内科的博客-CSDN博客

使用Winform的GDI进行流程图绘制,实现环节流转。

比如流程图如下:

         A---->B---->C

                            |

         F<----E<----D

新建windows应用程序WorkFlowDemo,将默认的Form1重命名为FormWorkFlow,引入开源ORM框架SqlSugar以及log4net,以及操作mysql的库MySql.Data.dll,然后添加对System.Configuration的引用。

一、默认的应用程序配置文件App.Config源程序如下:


 

二、增加操作mysql的类文件SugarDao,

SugarDao.cs源程序如下:

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using SqlSugar;
namespace WorkFlowDemo
{/// /// SqlSugar/// public class SugarDao{//禁止实例化private SugarDao(){}public static string ConnectionString(int index = 1){string reval = System.Configuration.ConfigurationManager.ConnectionStrings["mysql"].ConnectionString;return reval;}public static SqlSugarClient GetInstance(SqlSugar.DbType dbType= SqlSugar.DbType.MySql, int index = 1){return new SqlSugarClient(new ConnectionConfig(){DbType = dbType,ConnectionString = ConnectionString(index),InitKeyType = InitKeyType.Attribute,IsAutoCloseConnection = true,AopEvents = new AopEvents{OnLogExecuting = (sql, p) =>{Console.WriteLine(sql);Console.WriteLine(string.Join(",", p?.Select(it => it.ParameterName + ":" + it.Value)));}}});}/// /// 检查数据库连接/// public static bool CheckConnect(){SqlSugarClient db = GetInstance();string connectionString = db.CurrentConnectionConfig.ConnectionString;//连接字符串try{db.Open();return true;}catch (Exception ex){System.Windows.Forms.MessageBox.Show($"连接mysql数据库失败,【{ex.Message}】.\n连接字符串【{connectionString}】", "出错");return false;}finally{db.Close();}}}
}

三、增加操作类RawSql,

RawSql.cs源程序如下

using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace WorkFlowDemo
{/// /// 原生的sql增删改查/// public class RawSql{/// /// 执行原生的Sql与sql参数的insert、update、delete等操作,返回受影响的行数/// /// /// /// 数据库类型,一般是mysql/// 额外的连接数据库,2为新的数据库连接字符串/// public static int ExecuteCommand(string sql, Dictionary dict, SqlSugar.DbType dbType = SqlSugar.DbType.MySql, int index = 1){List parameters = DictToList(dict);using (var db = SugarDao.GetInstance(dbType, index)){return db.Ado.ExecuteCommand(sql, parameters);}}/// /// 执行原生的Sql与sql参数的select查询等操作,返回首行首列的数据/// /// /// /// 数据库类型,一般是mysql/// 额外的连接数据库,2为新的数据库连接字符串/// public static object GetScalar(string sql, Dictionary dict, SqlSugar.DbType dbType = SqlSugar.DbType.MySql, int index = 1){List parameters = DictToList(dict);using (var db = SugarDao.GetInstance(dbType, index)){return db.Ado.GetScalar(sql, parameters);}}/// /// 执行原生的Sql与sql参数的select查询等操作,返回一个数据表/// /// /// /// 数据库类型,一般是mysql/// 额外的连接数据库,2为新的数据库连接字符串/// public static DataTable GetDataTable(string sql, Dictionary dict, SqlSugar.DbType dbType = SqlSugar.DbType.MySql, int index = 1){List parameters = DictToList(dict);using (var db = SugarDao.GetInstance(dbType, index)){return db.Ado.GetDataTable(sql, parameters);}}/// /// 字典转参数列表/// /// /// private static List DictToList(Dictionary dict){List parameters = new List();for (int i = 0; dict != null && i < dict.Count; i++){KeyValuePair keyValuePair = dict.ElementAt(i);parameters.Add(new SugarParameter(keyValuePair.Key, keyValuePair.Value));}return parameters;}}
}

四、新建枚举类ArrowDirection

ArrowDirection.cs源程序如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace WorkFlowDemo
{/// /// 箭头方向:分水平方向Horizontal 和垂直方向Vertical/// [Flags]public enum ArrowDirection{/// /// 空,不绘制箭头/// None = 0,/// /// 垂直方向:向上/// Up = 1,/// /// 垂直方向:向下/// Down = 2,/// /// 水平方向:向左/// Left = 4,/// /// 水平方向:向右/// Right = 8}
}

五、窗体FormWorkFlow.Designer.cs设计器源程序如下:

namespace WorkFlowDemo
{partial class FormWorkFlow{/// /// 必需的设计器变量。/// private System.ComponentModel.IContainer components = null;/// /// 清理所有正在使用的资源。/// /// 如果应释放托管资源,为 true;否则为 false。protected override void Dispose(bool disposing){if (disposing && (components != null)){components.Dispose();}base.Dispose(disposing);}#region Windows 窗体设计器生成的代码/// /// 设计器支持所需的方法 - 不要修改/// 使用代码编辑器修改此方法的内容。/// private void InitializeComponent(){this.SuspendLayout();// // FormWorkFlow// this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;this.ClientSize = new System.Drawing.Size(884, 695);this.Name = "FormWorkFlow";this.Text = "工作流节点(环节)流转图";this.Load += new System.EventHandler(this.FormWorkFlow_Load);this.ResumeLayout(false);}#endregion}
}

六、核心流程图绘制FormWorkFlow.cs程序如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace WorkFlowDemo
{public partial class FormWorkFlow : Form{public FormWorkFlow(){InitializeComponent();}private void FormWorkFlow_Load(object sender, EventArgs e){//DataTable dt = RawSql.GetDataTable("select * from process_router where PreviousOperationName='' or PreviousOperationName is null", null);//if (dt == null || dt.Rows.Count == 0) //{//    MessageBox.Show("没有配置工艺路线【process_router】的起始工序,请检查工艺路线配置", "出错");//    return;//}//string nodeText = dt.Rows[0]["OperationName"].ToString();//Panel panel = new Panel();//panel.Location = new Point(10, 10);//panel.Name = "panel1";//panel.Size = new Size(160, 60);//this.Controls.Add(panel);//AddWorkFlowNode(panel, Color.Red, nodeText, ArrowDirection.Right);string nodeText;if (!PaintStartNode(out nodeText)) {return;}PaintNextNode(nodeText);}/// /// 绘制起始环节,返回是否查找到起始环节/// /// /// private bool PaintStartNode(out string nodeText) {nodeText = string.Empty;DataTable dt = RawSql.GetDataTable("select * from process_router where PreviousOperationName='' or PreviousOperationName is null", null);if (dt == null || dt.Rows.Count == 0){MessageBox.Show("没有配置工艺路线【process_router】的起始工序,请检查工艺路线配置", "出错");return false;}nodeText = dt.Rows[0]["OperationName"].ToString();Panel panel = new Panel();panel.Location = new Point(10, 10);panel.Name = "panel1";panel.Size = new Size(160, 60);this.Controls.Add(panel);AddWorkFlowNode(panel, Color.Green, nodeText, ArrowDirection.Right, 0);//PaintNodeAndArrowPanel(0, Color.Red, nodeText, false);return true;}/// /// 连续绘制工作流的当前环节与下一环节,以及最后一个终结环节/// /// private void PaintNextNode(string operationName){int index = 1;do{//获取当前节点(环节)的下一环节DataTable dt = RawSql.GetDataTable("select * from process_router where PreviousOperationName=@OperationName", new Dictionary() { { "OperationName", operationName } });if (dt != null && dt.Rows.Count > 0){operationName = dt.Rows[0]["OperationName"].ToString();//查找是否是终结环节dt = RawSql.GetDataTable("select * from process_router where PreviousOperationName=@OperationName", new Dictionary() { { "OperationName", operationName } });if (dt == null || dt.Rows.Count == 0){//当前环节 没有下一个环节 ,则认为是工序完成环节,不显示向右 或向下箭头PaintNodeAndArrowPanel(index, Color.Red, operationName, true);break;}PaintNodeAndArrowPanel(index, Color.Blue, operationName, false);}index++;} while (true);}/// /// 绘制环节节点以及流转箭头/// /// /// /// /// 是否是完成环节(最后一道工序)private void PaintNodeAndArrowPanel(int index, Color color, string operationName, bool isCompletedNode){Panel panel = new Panel();panel.Name = $"panel{index + 1}";int rowNumber = index / 3 * 2;switch (index % 6){case 1:panel.Location = new Point(10 + 160 * 2, 10 + 60 * rowNumber);panel.Size = new Size(160, 60);AddWorkFlowNode(panel, color, operationName, isCompletedNode ? ArrowDirection.None : ArrowDirection.Right, index);break;case 2:panel.Location = new Point(10 + 160 * 4, 10 + 60 * rowNumber);panel.Size = new Size(160, 60);AddWorkFlowNode(panel, color, operationName, isCompletedNode ? ArrowDirection.None : ArrowDirection.Down, index);break;case 3:panel.Location = new Point(10 + 160 * 2, 10 + 60 * rowNumber);panel.Size = new Size(160 * 2, 60);AddWorkFlowNode(panel, color, operationName, isCompletedNode ? ArrowDirection.None : ArrowDirection.Left, index);break;case 4:panel.Location = new Point(10 + 160 * 0, 10 + 60 * rowNumber);panel.Size = new Size(160 * 2, 60);AddWorkFlowNode(panel, color, operationName, isCompletedNode ? ArrowDirection.None : ArrowDirection.Left, index);break;case 5:panel.Location = new Point(10 + 160 * 0, 10 + 60 * rowNumber);panel.Size = new Size(160, 60);AddWorkFlowNode(panel, color, operationName, isCompletedNode ? ArrowDirection.None : ArrowDirection.Down, index);break;case 0:panel.Location = new Point(10 + 160 * 0, 10 + 60 * rowNumber);panel.Size = new Size(160, 60);AddWorkFlowNode(panel, color, operationName, isCompletedNode ? ArrowDirection.None : ArrowDirection.Right, index);break;}this.Controls.Add(panel);}private void AddWorkFlowNode(Panel panel, Color color, string text, ArrowDirection arrowDirection, int index) {panel.BackgroundImage = null;//清除背景//面板宽度为160,高度为60Bitmap bitmap = new Bitmap(panel.Width * 2, panel.Height);if (arrowDirection == ArrowDirection.Up || arrowDirection == ArrowDirection.Down) {bitmap = new Bitmap(panel.Width, panel.Height * 2);}Graphics graphics = Graphics.FromImage(bitmap);Rectangle rect = new Rectangle(0, 0, panel.Width, panel.Height);if (index % 6 == 3 || index % 6 == 4){//需要向左的环节,矩形绘制需要更新rect = new Rectangle(panel.Width / 2, 0, panel.Width / 2, panel.Height);}//Color color = Color.Blue;//string text = "Busbar焊接";graphics.FillRectangle(new SolidBrush(color), rect);graphics.DrawRectangle(new Pen(color), rect);AddTextAlignCenter(graphics, text, new Font("华文楷体", 16), rect);Pen pen = new Pen(Color.OrangeRed, 3);//画笔:线条颜色、粗细//DashStyle.Dot 代表虚线pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid;//实线pen.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;//设置线尾的样式为箭头switch (arrowDirection){case ArrowDirection.None:if (index % 6 == 3 || index % 6 == 4){panel.Location = new Point(panel.Location.X + 160, panel.Location.Y);}break;case ArrowDirection.Up:break;case ArrowDirection.Down:graphics.DrawLine(pen, new Point(panel.Width / 2, panel.Height), new Point(panel.Width / 2, panel.Height * 2));//将面板高度放大到两倍,下边部分用于显示线条panel.Height = panel.Height * 2;break;case ArrowDirection.Left:graphics.DrawLine(pen, new Point(panel.Width / 2, panel.Height / 2), new Point(0, panel.Height / 2));//将面板宽度放大到两倍,右边部分用于显示线条//panel.Width = panel.Width * 2;panel.Location = new Point(panel.Location.X + 160, panel.Location.Y);break;case ArrowDirection.Right:graphics.DrawLine(pen, new Point(panel.Width, panel.Height / 2), new Point(panel.Width * 2, panel.Height / 2));//将面板宽度放大到两倍,右边部分用于显示线条panel.Width = panel.Width * 2;break;}graphics.Dispose();pen.Dispose();panel.BackgroundImage = bitmap;}/// /// 将显示的文字放在矩形的中间/// /// /// /// /// private void AddTextAlignCenter(Graphics graphics, string text, Font font, Rectangle rect){SizeF sizeF = graphics.MeasureString(text, font);float destX = rect.X + (rect.Width - sizeF.Width) / 2;float destY = rect.Y + (rect.Height - sizeF.Height) / 2;graphics.DrawString(text, font, Brushes.Black, destX, destY);}}
}

 七、环节流程图运行如下:

 

相关内容

热门资讯

端午假期亲子游、出入境游火热   本报讯 近日,多个OTA平台发布的端午假期大数据报告显示,端午假期叠加“六一”儿童节,让亲子游产...
退市龙宇聘任54岁吕颖青为职工... 6月10日,退市龙宇(维权)公告,聘任吕颖青先生为公司职工代表董事。资料显示,吕颖青,男,1971年...
昌南大桥建设迎来阶段性节点新突...   本报讯(洪观新闻记者 徐景 文/图)2025年6月8日凌晨1点39分,随着混凝土泵车将最后一方混...
银行借力新消费“顶流”揽储 受... 转自:证券日报不仅是社交货币,更是揽储利器?新消费界“顶流”——那个露出獠牙、长相古怪的小精灵Lab...
Airwallex 创始人炮轰... 作者 | awxjack;kkone0x;EarningArtist;alexzuo4;BroLeo...
第五届国际葡萄酒文旅博览会举办 转自:人民日报  本报银川6月9日电 (记者张文、焦思雨)9日,第五届中国(宁夏)国际葡萄酒文化旅...
加州再起诉特朗普政府 【#加州再起诉特朗普政府#】#特朗普力挺调兵令# 连日来,美国加利福尼亚州因执法人员搜捕非法移民引发...
“热血”传递希望 爱心守护生命   本报讯(洪观新闻记者 肖周 文/图)为进一步提升卫生健康公共服务能力和政务公开水平,扎实推进无偿...
一瓶橙汁的诚信味道 □ 汪子轶 郭姗姗 本报记者 张华  初夏时节,生机盎然。“三峡门户”湖北宜昌,一江碧水,两岸青山。...
【环球财经】新西兰财长敦促联储... 转自:新华财经新华财经北京6月10日电 新西兰财长威利斯希望新西兰联储增加利率决策会议的频率,结束夏...
辽宁通管局深入推进电信业务“明...   本报讯(通讯员 李杨 记者 李世民)近期,按照工业和信息化部信息通信行业行风建设和纠风工作部署,...
宏观市场丨节假日提振住宿旅游价...   炒股就看金麒麟分析师研报,权威,专业,及时,全面,助您挖掘潜力主题机会! CPI,PPI5月C...
高考收官 未来可期 9日18时15分,2025年广东夏季高考结束。高考,是人生大考,当然重要,但也没那么重要。DeepS...
第十七届铁路装备展将在京举办 转自:千龙网第十七届中国国际现代化铁路技术装备展览会(MODERN RAILWAYS 2025,以下...
华扬联众(603825.SH)... 华扬联众(603825.SH)公告,公司拟与控股股东湘江集团共同投资设立合资公司湖南华扬文旅运营管理...
尹力、殷勇就推动生态涵养区绿色... 原标题:尹力、殷勇就推动生态涵养区绿色发展到平谷区调研,要求走生态优先、绿色低碳的高质量发展之路6月...
百名老区孩子看番禺主题活动开营... 羊城晚报讯 记者徐振天报道:6月9日,第四届“同一蓝天 共同幸福”——百名老区孩子看番禺主题活动开营...
我市停开3条定制公交线路   本报讯(洪观新闻记者 蔡欢)日前,记者获悉,为进一步优化公共交通资源配置,提升服务效能,经综合评...
你不知道的事,比你知道的事更有... 最近同事痴迷于塔勒布的《反脆弱》,并因阅读此书产生了许多感触和感想,塔勒布的书籍凝聚了他对于“不确定...
*ST海越聘任50岁颜战杭为副... 6月10日,*ST海越(维权)公告,聘任颜战杭先生为公司副总经理。资料显示,颜战杭,男,汉族,陕西铜...