h5网站建设包括什么义乌哪里有学做网站的
h5网站建设包括什么,义乌哪里有学做网站的,温州网页设计培训学校,培训人员网站建设一、前言接上一篇 .NET Core微服务 权限系统工作流#xff08;一#xff09;权限系统 #xff0c;再来一发工作流#xff0c;我在接触这块开发的时候一直好奇它的实现方式#xff0c;翻看各种工作流引擎代码#xff0c;探究其实现方式#xff0c;个人总结出来一个核心要… 一、前言 接上一篇 .NET Core微服务 权限系统工作流一权限系统 再来一发 工作流我在接触这块开发的时候一直好奇它的实现方式翻看各种工作流引擎代码探究其实现方式个人总结出来一个核心要点 实际上工作流引擎处理流转的核心要义是如何解析流转XML或者JSON或者其它持久化方式工作流通过解析XML或者JSON判断当前节点的状态和下个节点的信息并做出一些处理。感觉等于没说直白一点就是通过解析JSON文件得到下一步是谁处理。 工作流的流转线路实际上是固定死的排列组合即可知道所有可能的线路并没有想象中的那么难以理解。理解好这点那么接下来开发就很简单了垒代码而已手动微笑.ing。本系统着重分析工作流具体的实现方式不阐述具体的实现步骤详细代码请看GitHub地址。二、系统介绍深入研究过工作流的朋友可能会知道流程表单它分为两种1、定制表单。更加贴近业务但会累死开发人员。以前的公司都是这种方式开发这个和具体的业务逻辑有关系比较复杂的建议使用定制表单方式即开发人员把业务功能开发完了与流程关联即可。2、代码生成的表单。不需要编写代码系统可自动生成方便但是功能扩展性较差。当然各有好处。本系统两种方式都已经实现着重阐述定制流程。本系统人为规定一个流程只能绑定一个表单一个表单只能绑定一个流程。即一对一这是一切的前提。至于为什么这么做通常情况下一个流程的走向是跟表单逻辑是相挂钩的基本上不存在多个的可能性而且容易造成组织错乱有的话那就在再画一个流程一个表单。_^_三、工作流实现还是以面向数据库的方法来开发先看表wf_workflow 工作流表存放工作流基本信息wf_workflow_category 流程分类表wf_workflow_form 流程表单表分为两种类型系统生成表单和系统定制表单系统定制表单只存放URL地址wf_workflow_instance 流程实例表核心wf_workflow_instance_form 流程实例表单关联表wf_workflow_line 流程连线表。目前之存放两种相反的形式同意、不同意后期会添加自定义SQL判断业务逻辑流转节点wf_workflow_operation_history 流程操作历史表。用于获取审批意见等wf_workflow_transition_history 流程流转记录。用于获取 退回某一步获取节点等。目前工作流实现了这几个功能保存、提交、同意、不同意、退回、终止、流程图、审批意见后期会继续升级迭代如添加会签、挂起、通知等等目前这几个功能应该能应付一般业务需求了像会签这种功能99%用不到但是确是比较复杂的功能涉及并行、串行计算方式80%时间都花在这些用不到的功能上来所谓的二八法则吧。全部功能较多不一一列举了目前只有流程分类功能没实现后续再写吧但是不影响功能使用只是用于筛选而已流程设计界面采用GooFlow插件并对其代码做出一些修改界面确实比较难看设计比较简陋毕竟本人不会平面设计如果觉得不丑就当我没说。核心代码实际上就是解析JSON文件并写一些方便读取节点、连线的方法 1 /// summary 2 /// workflow context 3 /// /summary 4 public class MsWorkFlowContext : WorkFlowContext 5 { 6 /// summary 7 /// 构造器传参 8 /// /summary 9 /// param namedbworkflow/param 10 public MsWorkFlowContext(WorkFlow dbworkflow) 11 { 12 if (dbworkflow.FlowId default(Guid)) 13 { 14 throw new ArgumentNullException(FlowId, input workflow flowid is null); 15 } 16 if (dbworkflow.FlowJSON.IsNullOrEmpty()) 17 { 18 throw new ArgumentException(FlowJSON, input workflow json is null); 19 } 20 if (dbworkflow.ActivityNodeId null) 21 { 22 throw new ArgumentException(ActivityNodeId, input workflow ActivityNodeId is null); 23 } 24 25 this.WorkFlow dbworkflow; 26 27 dynamic jsonobj JsonConvert.DeserializeObject(this.WorkFlow.FlowJSON); 28 //获取节点 29 this.WorkFlow.Nodes this.GetNodes(jsonobj.nodes); 30 //获取连线 31 this.WorkFlow.Lines this.GetFromLines(jsonobj.lines); 32 33 this.WorkFlow.ActivityNodeId dbworkflow.ActivityNodeId default(Guid) ? this.WorkFlow.StartNodeId : dbworkflow.ActivityNodeId; 34 35 this.WorkFlow.ActivityNodeType this.GetNodeType(this.WorkFlow.ActivityNodeId); 36 37 //会签开始节点和流程结束节点没有下一步 38 if (this.WorkFlow.ActivityNodeType WorkFlowInstanceNodeType.ChatNode || this.WorkFlow.ActivityNodeType WorkFlowInstanceNodeType.EndRound) 39 { 40 this.WorkFlow.NextNodeId default(Guid);//未找到节点 41 this.WorkFlow.NextNodeType WorkFlowInstanceNodeType.NotRun; 42 } 43 else 44 { 45 var nodeids this.GetNextNodeId(this.WorkFlow.ActivityNodeId); 46 if (nodeids.Count 1) 47 { 48 this.WorkFlow.NextNodeId nodeids[0]; 49 this.WorkFlow.NextNodeType this.GetNodeType(this.WorkFlow.NextNodeId); 50 } 51 else 52 { 53 //多个下个节点情况 54 this.WorkFlow.NextNodeId default(Guid); 55 this.WorkFlow.NextNodeType WorkFlowInstanceNodeType.NotRun; 56 } 57 } 58 } 59 60 /// summary 61 /// 下个节点是否是多个 62 /// /summary 63 public bool IsMultipleNextNode { get; set; } 64 65 /// summary 66 /// 获取节点集合 67 /// /summary 68 /// param namenodesobj/param 69 /// returns/returns 70 private DictionaryGuid, FlowNode GetNodes(dynamic nodesobj) 71 { 72 DictionaryGuid, FlowNode nodes new DictionaryGuid, FlowNode(); 73 74 foreach (JObject item in nodesobj) 75 { 76 FlowNode node item.ToObjectFlowNode(); 77 if (!nodes.ContainsKey(node.Id)) 78 { 79 nodes.Add(node.Id, node); 80 } 81 if (node.Type FlowNode.START) 82 { 83 this.WorkFlow.StartNodeId node.Id; 84 } 85 } 86 return nodes; 87 } 88 89 /// summary 90 /// 获取工作流节点及以节点为出发点的流程 91 /// /summary 92 /// param namelinesobj/param 93 /// returns/returns 94 private DictionaryGuid, ListFlowLine GetFromLines(dynamic linesobj) 95 { 96 DictionaryGuid, ListFlowLine lines new DictionaryGuid, ListFlowLine(); 97 98 foreach (JObject item in linesobj) 99 {100 FlowLine line item.ToObjectFlowLine();101 102 if (!lines.ContainsKey(line.From))103 {104 lines.Add(line.From, new ListFlowLine { line });105 }106 else107 {108 lines[line.From].Add(line);109 }110 }111 112 return lines;113 }114 115 /// summary116 /// 获取全部流程线117 /// /summary118 /// returns/returns119 public ListFlowLine GetAllLines()120 {121 dynamic jsonobj JsonConvert.DeserializeObject(this.WorkFlow.FlowJSON);122 ListFlowLine lines new ListFlowLine();123 foreach (JObject item in jsonobj.lines)124 {125 FlowLine line item.ToObjectFlowLine();126 lines.Add(line);127 }128 return lines;129 }130 131 /// summary132 /// 根据节点ID获取From流入的线条133 /// /summary134 /// param namenodeid/param135 /// returns/returns136 public ListFlowLine GetLinesForFrom(Guid nodeid)137 {138 var lines GetAllLines().Where(m m.To nodeid).ToList();139 return lines;140 }141 142 public ListFlowLine GetLinesForTo(Guid nodeid)143 {144 var lines GetAllLines().Where(m m.From nodeid).ToList();145 return lines;146 }147 148 /// summary149 /// 获取全部节点150 /// /summary151 /// returns/returns152 public ListFlowNode GetAllNodes()153 {154 dynamic jsonobj JsonConvert.DeserializeObject(this.WorkFlow.FlowJSON);155 ListFlowNode nodes new ListFlowNode();156 foreach (JObject item in jsonobj.nodes)157 {158 FlowNode node item.ToObjectFlowNode();159 nodes.Add(node);160 }161 return nodes;162 }163 164 /// summary165 /// 根据节点ID获取节点类型166 /// /summary167 /// param namenodeId/param168 /// returns/returns169 public WorkFlowInstanceNodeType GetNodeType(Guid nodeId)170 {171 var _thisnode this.WorkFlow.Nodes[nodeId];172 return _thisnode.NodeType();173 }174 175 /// summary176 /// 根据节点id获取下个节点id177 /// /summary178 /// param namenodeId/param179 /// returns/returns180 public ListGuid GetNextNodeId(Guid nodeId)181 {182 ListFlowLine lines this.WorkFlow.Lines[nodeId];183 if (lines.Count 1)184 {185 this.IsMultipleNextNode true;186 }187 return lines.Select(m m.To).ToList();188 }189 190 /// summary191 /// 节点驳回192 /// /summary193 /// param namerejectType驳回节点类型/param194 /// param namerejectNodeid要驳回到的节点/param195 /// returns/returns196 public Guid RejectNode(NodeRejectType rejectType, Guid? rejectNodeid)197 {198 switch (rejectType)199 {200 case NodeRejectType.PreviousStep:201 return this.WorkFlow.PreviousId;202 case NodeRejectType.FirstStep:203 var startNextNodeId this.GetNextNodeId(this.WorkFlow.StartNodeId).First();204 return startNextNodeId;205 case NodeRejectType.ForOneStep:206 if (rejectNodeid null || rejectNodeid default(Guid))207 {208 throw new Exception(驳回节点没有值);209 }210 var fornode this.WorkFlow.Nodes[rejectNodeid.Value];211 return fornode.Id;212 case NodeRejectType.UnHandled:213 default:214 return this.WorkFlow.PreviousId;215 }216 }217 218 }流程流转代码主要部分这段代码是处理流转核心功能只完成了部分核心功能 1 /// summary 2 /// 流程过程流转处理 3 /// /summary 4 /// param namemodel/param 5 /// returns/returns 6 public async TaskWorkFlowResult ProcessTransitionFlowAsync(WorkFlowProcessTransition model) 7 { 8 WorkFlowResult result new WorkFlowResult(); 9 switch (model.MenuType)10 {11 case WorkFlowMenu.Submit:12 break;13 case WorkFlowMenu.ReSubmit:14 result await ProcessTransitionReSubmitAsync(model);15 break;16 case WorkFlowMenu.Agree:17 result await ProcessTransitionAgreeAsync(model);18 break;19 case WorkFlowMenu.Deprecate:20 result await ProcessTransitionDeprecateAsync(model);21 break;22 case WorkFlowMenu.Back:23 result await ProcessTransitionBackAsync(model);24 break;25 case WorkFlowMenu.Stop://刚开始提交下一个节点未审批情况流程发起人可以终止26 result await ProcessTransitionStopAsync(model);27 break;28 case WorkFlowMenu.Cancel:29 break;30 case WorkFlowMenu.Throgh:31 break;32 case WorkFlowMenu.Assign:33 break;34 case WorkFlowMenu.View:35 break;36 case WorkFlowMenu.FlowImage:37 break;38 case WorkFlowMenu.Approval:39 break;40 case WorkFlowMenu.CC:41 break;42 case WorkFlowMenu.Suspend:43 break;44 case WorkFlowMenu.Resume:45 break;46 case WorkFlowMenu.Save:47 case WorkFlowMenu.Return:48 default:49 result WorkFlowResult.Error(未找到匹配按钮);50 break;51 }52 return result;53 }如果以定制表单关联流程的方式开发会遇到一个重要问题流程状态如何与表单同步因为工作流与业务流是区分开的怎么办 我的做法是以请假为例让实体先继承流程状态实体通过CAP的方式推送和订阅我以前的公司工作流是通过页面回调的方式实现我感觉这个很不靠谱实际上也是经常出问题流程状态的判断WfWorkflowInstance实体下的两个字段 这块可能不太好理解尤其是没有开发过的朋友简单解释下IsFinish 是表示流程运行的状态Status表示用户操作流程的状态我们判断这个流程是否结束不能单纯的判断根据IsFinish进行判断举个例子请假 我提交了一个请假申请下个节点审批不同意。你说这个流程有没有结束当然结束了只不过它没有审批通过而已。简而言之IsFinish表示流程流转是否结束即是否最终到了最后一个结束节点。 1 #region 结合起来判断流程是否结束 2 /* 流转状态判断 实际情况组合 3 * IsFinish1 StatusWorkFlowStatus.IsFinish 表示通过 4 * IsFinishnull StatusWorkFlowStatus.UnSubmit 表示未提交 5 * IsFinish0 StatusWorkFlowStatus.Running 表示运行中 6 * IsFinish0 StatusWorkFlowStatus.Deprecate 表示不同意 7 * IsFinish0 StatusWorkFlowStatus.Back 表示流程被退回 8 * **/ 9 /// summary10 /// 流程节点是否结束11 /// 注此字段代表工作流流转过程中运行的状态判断12 /// /summary13 public int? IsFinish { get; set; }14 15 /// summary16 /// 用户操作状态see crefWorkFlowStatus/17 /// 注此字段代表用户操作流程的状态18 /// /summary19 public int Status { get; set; }20 21 #endregion至于页面审批按钮的展示因为这个功能是公用的我把它写在了组件里面共两个菜单组件一个是定制一个是系统生成代码稍微有些不同组件视图代码比较多就不展示了。下面走一个不同意的请假流程1、wms账号先选择要发起的流程2、流程发起界面3、流程提交之后的界面注终止当用户提交表单之后下个节点未进行审批的时候流程发起人有权终止取消流程4、wangwu账号登录5、结果展示6、审批意见查看7、流程图查看绿色节点表示流程当前节点。8、也可以在OA员工请假看到结果注因为工作流引擎不涉及具体的业务逻辑通常与OA系统进行表单绑定所以我建了OA服务并简单写了个请假流程方便测试。工作流依赖于之前的权限系统如果登录人员显示没有权限请先进行授权四、结束 每个程序员刚毕业的时候都有一种我要独立写一个超级牛逼系统的冲动我也是都不记得多少年了断断续续坚持到现在虽然不算完善更谈不上多么牛逼写这两篇算是给自己一个交代吧。如果大家觉得有研究价值的话我会继续升级迭代。运行方式参考 上一篇 末尾管理员登录账号wms密码所有账号密码都是123代码地址:https://github.com/wangmaosheng/MsSystem-BPM-ServiceAndWebApps如果觉得有点作用的话可以 start 下后续会持续更新。原文地址https://www.cnblogs.com/wms01/p/10940565.html.NET社区新闻深度好文欢迎访问公众号文章汇总 http://www.csharpkit.com
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/88282.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!