.net erp(办公oa)开发平台架构之流程服务概要介绍
背景
搭建一个适合公司erp业务的开发平台。
架构概要图:
流程引擎开发平台:
包含流程引擎设计器,流程管理平台,流程引擎服务。目前只使用单个数据库进行管理。
流程引擎设计器
采用silverlight进行开发,本质是对流程模型进行设计,并生成xml。包含:人工节点,自动节点,并行开始节点,并行结束节点,消息节点,文本节点。
示例模型定义图形:
示例模型定义xml:
<?xml version="1.0" encoding="gb2312"?>
<ProcessModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<BaseInfo>
<Key>ddd</Key>
<Title>新建模型</Title>
<Description>发起人</Description>
<CreateTime>0001-01-01T00:00:00</CreateTime>
<Author>
<StaffNo>34</StaffNo>
<UserName>车江毅1</UserName>
</Author>
<Type>Common</Type>
<Compilation>Debug</Compilation>
</BaseInfo>
<Variables>
<Variable Name="myValue1" Value="今天天气好晴朗" Mode="Flow" />
<Variable Name="myValue2" Value="v2" Mode="Flow" />
<Variable Name="myValue3" Value="v3" Mode="Flow" />
<Variable Name="myValue4" Value="true" Mode="Flow" />
</Variables>
<Nodes>
<BaseNode xsi:type="StartNode" Key="start1" Text="开始" Location="236 10">
<Routes>
<Route To="auto1" Text="" Location="0 0">
<RouteScripts />
</Route>
</Routes>
<BeginScripts />
<EndScripts />
</BaseNode>
<BaseNode xsi:type="AutoNode" Key="auto1" Text="系统判断" Location="236 95">
<Routes>
<Route To="man1" Text="线1" Location="0 0">
<Code><![CDATA[myValue4=='true']]></Code>
<RouteScripts />
</Route>
<Route To="人工2" Text="线" Location="0 0">
<Code><![CDATA[myValue4=='false']]></Code>
<RouteScripts />
</Route>
</Routes>
<BeginScripts />
<EndScripts />
<Scripts>
<Script>
<Code><![CDATA[api.Forword('http://webservice.webxml.com.cn/webservices/ChinaTVprogramWebService.asmx','getTVstationDataSet','theAreaID:2')]]></Code>
</Script>
<Script>
<Code><![CDATA[api.UpdateVariable('063550')]]></Code>
</Script>
</Scripts>
</BaseNode>
<BaseNode xsi:type="ManNode" Key="man1" Text="人工1" Location="167 205">
<Routes>
<Route To="并行开始1" Text="线" Location="0 0">
<Code><![CDATA[]]></Code>
<RouteScripts />
</Route>
</Routes>
<BeginScripts />
<EndScripts />
<Participants>
<Participant Mode="Code">
<Code><![CDATA[api.Split('034','#')]]></Code>
</Participant>
<Participant Mode="Variable">
<Code><![CDATA[myValue3]]></Code>
</Participant>
</Participants>
<Solt OrderCount="2" Mode="Once" />
<Decisions>
<Decision Text="同意" />
<Decision Text="不同意" />
</Decisions>
</BaseNode>
<BaseNode xsi:type="EndNode" Key="结束" Text="结束" Location="238 732">
<Routes />
<BeginScripts />
<EndScripts />
</BaseNode>
<BaseNode xsi:type="ManNode" Key="人工2" Text="人工2" Location="324 203">
<Routes>
<Route To="并行开始1" Text="线" Location="0 0">
<Code><![CDATA[]]></Code>
<RouteScripts />
</Route>
</Routes>
<BeginScripts />
<EndScripts />
<Participants />
<Decisions />
</BaseNode>
<BaseNode xsi:type="ParallelBeginNode" Key="并行开始1" Text="并行签入" Location="237.047607421875 312">
<Routes>
<Route To="人工3" Text="线" Location="0 0">
<Code><![CDATA[]]></Code>
<RouteScripts />
</Route>
<Route To="人工4" Text="线" Location="0 0">
<Code><![CDATA[]]></Code>
<RouteScripts />
</Route>
</Routes>
<BeginScripts />
<EndScripts />
</BaseNode>
<BaseNode xsi:type="ParallelFinishNode" Key="并行结束1" Text="并行结束1" Location="240 571">
<Routes>
<Route To="消息1" Text="线" Location="0 0">
<Code><![CDATA[]]></Code>
<RouteScripts />
</Route>
</Routes>
<BeginScripts />
<EndScripts />
</BaseNode>
<BaseNode xsi:type="ManNode" Key="人工3" Text="人工3" Location="95 378">
<Routes>
<Route To="自动1" Text="线" Location="0 0">
<Code><![CDATA[]]></Code>
<RouteScripts />
</Route>
</Routes>
<BeginScripts />
<EndScripts />
<Participants />
<Decisions />
</BaseNode>
<BaseNode xsi:type="ManNode" Key="人工4" Text="人工4" Location="392 379">
<Routes>
<Route To="自动2" Text="线" Location="0 0">
<Code><![CDATA[]]></Code>
<RouteScripts />
</Route>
</Routes>
<BeginScripts />
<EndScripts />
<Participants />
<Decisions />
</BaseNode>
<BaseNode xsi:type="AutoNode" Key="自动1" Text="自动1" Location="98 483">
<Routes>
<Route To="并行结束1" Text="线" Location="0 0">
<Code><![CDATA[]]></Code>
<RouteScripts />
</Route>
</Routes>
<BeginScripts />
<EndScripts />
<Scripts />
</BaseNode>
<BaseNode xsi:type="AutoNode" Key="自动2" Text="自动2" Location="394.714294433594 474.952362060547">
<Routes>
<Route To="并行结束1" Text="线" Location="0 0">
<Code><![CDATA[]]></Code>
<RouteScripts />
</Route>
</Routes>
<BeginScripts />
<EndScripts />
<Scripts />
</BaseNode>
<BaseNode xsi:type="MessageNode" Key="消息1" Text="消息1" Location="239 656">
<Routes>
<Route To="结束" Text="线" Location="0 0">
<Code><![CDATA[]]></Code>
<RouteScripts />
</Route>
</Routes>
<BeginScripts />
<EndScripts />
<Participants />
<MessageVariables />
<TemplateKey>0</TemplateKey>
<TemplateName />
</BaseNode>
</Nodes>
</ProcessModel>
常规界面如下:
流程管理平台
包含:流程模型管理,流程管理,流程任务管理,流程操作记录,流程服务接口日志查询,流程异常查询,流程流转调试日志查询,开发者用户管理等。
可以管理流程模型历史版本及版本切换,流程异常时候的流程节点切换,流程任务的转交等。
界面如下:
流程服务
包含:流程接口和流程任务接口。
/// <summary>
/// 业务流程服务接口
/// </summary>
public interface IProcessService
{
/// <summary>
/// 获取业务流程
/// </summary>
/// <param name="guid">业务流程ID</param>
ProcessInfo GetProcessById(Guid guid);
/// <summary>
/// 批量获取业务流程
/// </summary>
/// <param name="guids">多个业务流程ID</param>
ProcessListInfo GetProcessesByIds(List<Guid> guids);
/// <summary>
/// 根据流程发布者,获取业务流程列表
/// </summary>
/// <param name="user">用户的信息 参看UserInfo对象注释</param>
/// <param name="modelkeys">模型key 可选(多个)</param>
/// <param name="keyword">关键词(标题) 可选</param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <returns></returns>
ProcessListInfo GetProcessListByOriginator(UserInfo user, List<string> modelkeys, string keyword, int pageIndex, int pageSize);
/// <summary>
/// 根据流程参与者,获取业务流程列表
/// </summary>
/// <param name="user">用户的信息 参看UserInfo对象注释</param>
/// <param name="modelkeys">模型key 可选(多个)</param>
/// <param name="keyword">关键词(标题) 可选</param>
/// <param name="nodekey">任务所在节点key 可选</param>
/// <param name="state">任务完成状态</param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <returns></returns>
ProcessListInfo GetProcessListByParticipant(UserInfo user, List<string> modelkeys, string keyword, string nodekey, EnumTaskStateQuery state, int pageIndex, int pageSize);
/// <summary>
/// 根据模型keys, 获取业务流程列表
/// </summary>
/// <param name="modelkeys">模型关键词 (多个)</param>
/// <param name="keyword">关键词(标题) 可选</param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <returns></returns>
ProcessListInfo GetProcessListByModel(List<string> modelkeys, string keyword, int pageIndex, int pageSize);
/// <summary>
/// 创建业务流程
/// </summary>
/// <param name="modelkey">业务流程对应的模型key</param>
/// <param name="title">业务流程标题</param>
/// <param name="description">业务流程描述</param>
/// <param name="variables">业务流程使用变量 可选</param>
/// <param name="user">业务流程发起人 参看UserInfo对象注释</param>
/// <param name="operationArgs">操作记录 可选</param>
/// <returns></returns>
ProcessInfo CreateProcess(string modelkey, string title, string description, List<Variable> variables, UserInfo user, OperationRecordInfoArgs operationArgs);
/// <summary>
/// 更新业务流程
/// </summary>
/// <param name="guid">业务流程的ID</param>
/// <param name="title">业务流程的标题</param>
/// <param name="description">业务流程的描述</param>
/// <param name="variables">业务员流程的变量 可选</param>
void UpdateProcess(Guid guid, string title, string description, List<Variable> variables);
/// <summary>
/// 结束业务流程
/// </summary>
/// <param name="guid">业务流程的ID</param>
void FinishProcess(Guid guid, UserInfo user, OperationRecordInfoArgs operationArgs);
/// <summary>
/// 创建流程操作记录
/// </summary>
/// <param name="user">操作用户不能为空</param>
/// <param name="operationArgs">操作记录不能为空</param>
void CreateProcessOperationRecord(Guid guid, UserInfo user, OperationRecordInfoArgs operationArgs);
}
/// <summary>
/// 任务服务接口
/// </summary>
public interface ITaskService
{
/// <summary>
/// 根据任务id,获取任务
/// </summary>
/// <param name="id">任务id</param>
/// <returns></returns>
TaskInfo GetTaskByID(string id);
/// <summary>
/// 根据任务id,批量获取任务
/// </summary>
/// <param name="ids">多个任务id</param>
/// <returns></returns>
TaskListInfo GetTasksByIDs(List<string> ids);
/// <summary>
/// 根据业务流程id,获取任务信息列表
/// </summary>
/// <param name="state">任务状态</param>
/// <param name="processId">业务流程id</param>
/// <returns></returns>
TaskListInfo GetTaskListByProcessID(EnumTaskStateQuery state, Guid processId);
/// <summary>
/// 根据用户,获取任务信息列表
/// </summary>
/// <param name="user">用户的信息 参看UserInfo对象注释</param>
/// <param name="state">任务状态</param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <returns></returns>
TaskListInfo GetTaskListByUser(UserInfo user, EnumTaskStateQuery state, int pageIndex, int pageSize);
/// <summary>
/// 根据用户和流程,获取任务信息列表
/// </summary>
/// <param name="user">用户的信息 参看UserInfo对象注释</param>
/// <param name="processId">业务流程id</param>
/// <param name="nodekey">当前活动节点key 可选</param>
/// <param name="state">任务状态</param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <returns></returns>
TaskListInfo GetTaskListByUserAndProcess(UserInfo user, Guid processId, string nodekey,EnumTaskStateQuery state, int pageIndex, int pageSize);
/// <summary>
/// 根据业务流程模型key,获取任务信息列表
/// </summary>
/// <param name="user">用户的信息 参看UserInfo对象注释</param>
/// <param name="modelkeys">业务模型key 可选(多个)</param>
/// <param name="nodekey">当前活动节点key 可选</param>
/// <param name="state">任务状态</param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <returns></returns>
TaskListInfo GetTaskListByUserAndModel(UserInfo user, List<string> modelkeys, string nodekey, EnumTaskStateQuery state, int pageIndex, int pageSize);
/// <summary>
/// 执行任务
/// </summary>
/// <param name="id">任务id</param>
/// <param name="action">任务的动作 例如:“同意”“不同意”</param>
/// <param name="variables">流程参数 可选</param>
/// <param name="operationArgs">操作信息 必填</param>
TaskInfo ExecuteTask(string id, string action, List<Variable> variables, OperationRecordInfoArgs operationArgs); /// <summary>
/// 转交任务
/// </summary>
/// <param name="id">任务id</param>
/// <param name="toUser">任务转交人信息 参看UserInfo对象注释</param>
/// <param name="operationArgs">操作信息 传null则无转交操作记录</param>
TaskInfo TransferTaskWithOperationRecordInfoArgs(string id, UserInfo toUser, OperationRecordInfoArgs operationArgs);
分布式架构概想:
分布式拆库方案:流程维度和用户维度,流程维度数据库按照流程定义模型的唯一标识hash,来拆分到不同的数据库。所有流程创建和流程任务的创建都在不同的数据库中。用户维度数据库按照用户标识hash,来拆分到不同的数据库。
拆库优点:数据被拆分,不影响同一个业务流程流转,性能会得到提升。
拆库缺点:采用异步消息通知,做用户代办任务和完成任务冗余及同步。采用BI工具或者hadoop等进行数据报表等分析。开发,维护复杂度等都会提升。
结论:如果不是做大型产品或服务,不会进行分布式架构。
(此文只做阶段性的总结,也许对同样做流程引擎的人有些启发,也欢迎交流。分布式相关架构可以参考本人其他文章)
.net erp(办公oa)开发平台架构之流程服务概要介绍的更多相关文章
- .net erp(办公oa)开发平台架构概要说明之表单设计器
背景:搭建一个适合公司erp业务的开发平台. 架构概要图: 表单设计开发部署示例图 表单设计开发部署示例说明1)每个开发人员可以自己部署表单设计至本地一份(当然也可以共用一套开发环境,但是如 ...
- .net工作流引擎ccflow开发平台属性功能的隐藏显示介绍
关键字: 工作流程管理系统 工作流引擎 asp.net工作流引擎 java工作流引擎. 表单引擎 工作流功能说明 工作流设计 工作流快速开发平台 业务流程管理 bpm工作流系统 java工 ...
- C# C/S系统软件开发平台架构图(原创)
企业版V4.0 - 架构图 企业版V4.0 - 桥接功能.后台连接策略 桥接功能是指应用策略模式,由用户配置本地INI文件选择ADO直连(ADO-Direct)或者调用WCF服务接口访问远程服务器后台 ...
- Agile.Net 组件式开发平台 - 平台系统介绍
平台介绍 Agile.Net 组件式开发平台是一款针对企业级产品的开发框架,平台架构基于SOA服务体系,多层组件式架构打造.平台提供企业应用开发所需的诸如ORM.IOC.WCF.EBS.SOA等分布式 ...
- 从 Airflow 到 Apache DolphinScheduler,有赞大数据开发平台的调度系统演进
点击上方 蓝字关注我们 作者 | 宋哲琦 ✎ 编 者 按 在不久前的 Apache DolphinScheduler Meetup 2021 上,有赞大数据开发平台负责人 宋哲琦 带来了平台调度系统 ...
- 可视化设计,类Excel的快速开发平台
活字格Web应用生成器,是可视化设计,类Excel的快速开发平台,接下来给大家介绍如何体现这些特点. 一.可视化设计 网页系统的开发,包含UI设计+代码编写的工作,最终形成网页系统.这要求系统开发人员 ...
- 分享一个全开源的ASP.NET快速开发平台,能快速开发OA CRM ERP 等系统
bingo炸了 2017/3/30 16:28:14 阅读(870) 评论(0) 公司业务量比较大,接了很多项目,为了缩短开发周期老板让我牵头搭建了一个快速开发平台. 我们主要的业务是做OA.CRM. ...
- 使用 asp.net mv4开发企业级办公OA
大家好!这是我第一次写asp.net 开发笔记,哪里写的不好,请见谅! 本程序是一个在线办公(OA)系统 B/S项目: 项目开发环境:Microsoft Visual Studio 2012 + Sq ...
- ERP开源框架 + 二次开发平台 介绍
经历了多年软件开发,深受网络大侠们的资源共享才得以有所成绩, 本人主要是做企业ERP软件,一直有个感受,开发具体某个功能不难,但随着需求的增加,管理庞大的代码却成了最大的问题 而为企业管理所做的开发, ...
随机推荐
- 使用Monit监控本地进程
目前用它监控某些服务,失败自动重启,同时监控特定的日志文件,如果有变化,就发邮件报警 安装不细写了,网上好多 我先用cat /proc/version看了下我的系统是el6的,于是wget http: ...
- 关于微软HttpClient使用,避免踩坑
最近公司对于WebApi的场景使用也越来越加大了,随之而来就是Api的客户端工具我们使用哪个?我们最常用的估计就是HttpClient,在微软类库中命名空间地址:System.Net.Http,是一个 ...
- 学习ASP.NET Core, 怎能不了解请求处理管道[3]: 自定义一个服务器感受一下管道是如何监听、接收和响应请求的
我们在<服务器在管道中的"龙头"地位>中对ASP.NET Core默认提供的具有跨平台能力的KestrelServer进行了介绍,为了让读者朋友们对管道中的服务器具有更 ...
- 高频交易算法研发心得--MACD指标算法及应用
凤鸾宝帐景非常,尽是泥金巧样妆. 曲曲远山飞翠色:翩翩舞袖映霞裳. 梨花带雨争娇艳:芍药笼烟骋媚妆. 但得妖娆能举动,取回长乐侍君王. [摘自<封神演义>纣王在女娲宫上香时题的诗] 一首定 ...
- CSS 3学习——transform 2D转换
首先声明一点,transform属性不为none的元素是它的定位子元素(绝对定位和固定定位)的包含块,而且对内创建一个新的层叠上下文. 注意:可以通过 transform-box 属性指定元素的那个盒 ...
- Kooboo CMS技术文档之四:Kooboo CMS的站点组成部分
Kooboo CMS本着功能独立分离的原则,将站点分为三部分组成:用户管理,站点管理和内容数据库管理.各个功能之间既可独立使用,也可以容易组成在一起形成一个完整的系统. 用户管理 管理整个系统内的用户 ...
- MSYS2——Windows平台下模拟linux环境的搭建
最近从MSYS1.0迁移到了MSYS2.0,简单讲,MSYS2.0功能更强大,其环境模拟更加符合linux.虽然本身来自cygwin,但其集成了pacman软件管理工具,很有linux范,并且可以直接 ...
- 推荐10款超级有趣的HTML5小游戏
HTML5的发展速度比任何人的都想像都要更快.更加强大有效的和专业的解决方案已经被开发......甚至在游戏世界中!这里跟大家分享有10款超级趣味的HTML5游戏,希望大家能够喜欢! Kern Typ ...
- Javascript学习笔记
Javascript 2016年12月19日整理 JS基础 Chapter1 JS是一门运行在浏览器客户端的脚本编程语言,前台语言 组成部分 1. ECMAscript JS标准 2. DOM 通过J ...
- 计算Div标签内Checkbox个数或已被disabled的个数
先看下面的html: 计算div内的checkbox个数:$('#divmod input[type="checkbox"]').length 计算div内checkbox被dis ...