mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-03-03 00:00:49 +08:00
更新了自述文件,以及一些优化。
This commit is contained in:
64
README.md
64
README.md
@@ -1,14 +1,12 @@
|
||||
# 自述
|
||||
基于Dotnet 8 的流程可视化编辑器,需二次开发。
|
||||
基于Dotnet 8 的流程可视化框架,运行以来、运行环境、编辑环境全部开源,可二次开发。
|
||||
不定期在Bilibili个人空间上更新相关的视频。
|
||||
https://space.bilibili.com/33526379
|
||||
|
||||
|
||||
# 计划任务 2024年10月28日更新
|
||||
* 重新完善远程管理与远程客户端的功能(目前仅支持远程修改节点属性、添加/移除节点、启动流程、停止流程)
|
||||
* 重新完善节点树视图、IOC容器对象视图(目前残废版)
|
||||
* 计划实现单步执行(暂未想到如何在不影响异步流程的前提下停止流程)
|
||||
* 考虑模仿AST的方式,将流程图以“Node token → C# Code”的方式进行原生代码支持
|
||||
# 计划任务 2025年6月1日更新
|
||||
* 重新实现远程控制逻辑(添加对多画布多客户端在线支持)
|
||||
|
||||
# 如何加载我的DLL?
|
||||
为你的工程添加**Serein.Library**项目引用(也可在Negut上下载),使用 **DynamicFlow** 特性标记你的类,可以参照 **Net461DllTest** 的实现(该示例工程的设计并不完善,并未做依赖分离,仅做参考)。编译为 Dll文件 后,拖入到软件中即可。
|
||||
如果你不想下载整个工程文件,“FLowEdit”目录下放有“FlowEdit可视化流程编辑器.zip”压缩包,可以直接解压使用(但可能需要你安装 .Net8 运行环境)。
|
||||
@@ -17,7 +15,7 @@ https://space.bilibili.com/33526379
|
||||
* 动作节点 - Action
|
||||
* 触发器节点 - Flipflop
|
||||
* UI节点 - UI
|
||||
# 关于 IDynamicContext 说明(重要)**
|
||||
# 关于 IDynamicContext 说明(重要)
|
||||
* 基本说明:IDynamicContext 是节点之间传递数据的接口、载体,其实例由 FlowEnvironment 运行环境自动实现,内部提供全局单例的环境接口,用以注册、获取实例(单例模式),一般情况下,你无须关注 FlowEnvironment 对外暴露的属性方法。
|
||||
* 重要概念:
|
||||
* 每个节点其实对应类库中的某一个方法,这些方法组合起来,加上预先设置的逻辑分支,就是一个完整的节点流。在这个节点流当中,从第一个节点开始、直到所有可达的节点,都会通过同一个流程上下文传递、共享数据。为了符合多线程操作的理念,每个运行起来的节点流之间,流程数据并不互通,从根本隔绝了“脏数据”的产生。
|
||||
@@ -50,10 +48,10 @@ https://space.bilibili.com/33526379
|
||||
* 入参:根据目标节点变化。
|
||||
* 描述:有时我们需要将流程图的逻辑解耦,单独使用某个画布编写逻辑,抽取出一个通用的处理模板,在其它流程图中像接口一样进行调用。
|
||||
* 使用方式:
|
||||
0. 创建两个画布,分别命名画布A,画布B。
|
||||
1. 在画布A上,选择希望暴露出去的一个节点,勾选“全局公开”。
|
||||
2. 在画布B上,拖拽创建“流程接口”节点,画布选择“画布A”,节点选择公开的节点。
|
||||
3. 在画布B上正常调用即可。
|
||||
1. 创建两个画布,分别命名画布A,画布B。
|
||||
2. 在画布A上,选择希望暴露出去的一个节点,勾选“全局公开”。
|
||||
3. 在画布B上,拖拽创建“流程接口”节点,画布选择“画布A”,节点选择公开的节点。
|
||||
4. 在画布B上正常调用即可。
|
||||
* 关于“参数共享”设置的说明:
|
||||
* 如果启用了,那么流程接口对应的节点,入参参数将在全局保持一致,一处地方修改后,处处同步(仅限于启用了这一设置的相同的流程接口节点)。
|
||||
* 如果没有启用,那么流程接口将会从目标节点拷贝相同的入参,单独使用,并不受目标节点的入参参数修改而修改。
|
||||
@@ -146,24 +144,50 @@ https://space.bilibili.com/33526379
|
||||
* **ExpCondition - 条件表达式节点**
|
||||
* 入参: 自定义。
|
||||
* 描述:与表达式节点不同,条件表达式节点是判断条件是否成立,如果成立,返回true,否则返回false,如果表达式执行失败,而进入 error 分支。
|
||||
* 增加描述:如果入参数据为某个对象,需要得到其属性/字段,可以在表达式输入框使用“ .[property]/[field]< type> [op] value ”的方式判断条件,注意,必须使用“.”符号,这有助于显然的表达需要从入参对象中取内部某个值,另外,也可以在入参数据编辑框,使用“@Get .[property]/[field]”的方式重新定义入参数据。
|
||||
* 使用方式:
|
||||
* 入参说明:默认从上一节点获取,也可以显式设定值,也可以参考表达式节点,使用“@Get .[property]/[field]”的方式重新定义入参数据,用以条件表达式判断。
|
||||
* 条件表达式:默认“PASS”,代表跳过判断直接进入下一个分支。
|
||||
* 条件表达式格式“.[property]/[field]< type> [op] value”,注意,开头必须使用“.”符号,这有助于显然的表达需要从入参对象中取内部某个值。
|
||||
* 表达式符号说明:
|
||||
* [property] /[field] : 属性/字段
|
||||
* [op] : 操作符
|
||||
1. bool表达式:==
|
||||
2. 数值表达式 :==、>=、 <=、in a-b (表示判断是否在a至b的数值范围内), !in a-b(取反);
|
||||
3. 文本表达式:==/equals(等于)、!=/notequals(不等于)、c/contains(出现过)、nc/doesnotcontain(没有出现过)、sw/startswith(开头等于)、ew/endswith(结尾等于)
|
||||
* [value] : 条件值
|
||||
* [property] /[field] : 属性/字段
|
||||
* [op] : 操作符
|
||||
1. bool表达式:==
|
||||
2. 数值表达式 :==、>=、 <=、in a-b (表示判断是否在a至b的数值范围内), !in a-b(取反);
|
||||
3. 文本表达式:==/equals(等于)、!=/notequals(不等于)、c/contains(出现过)、nc/doesnotcontain(没有出现过)、sw/startswith(开头等于)、ew/endswith(结尾等于)
|
||||
* < type> :指定需要转换为某个类型,可不选。
|
||||
* [value] : 条件值
|
||||
* 使用示例:
|
||||
~~~
|
||||
场景1:上一个节点传入了该对象(伪代码):
|
||||
class Data
|
||||
{
|
||||
string Name; // 性能
|
||||
string Age; // 年龄,外部传入了文本类型
|
||||
string IdentityCardNumber; // 身份证号
|
||||
|
||||
}
|
||||
需求:需要判断年龄是否在某个区间,例如需要大于18岁,小于35岁。
|
||||
条件表达式:.Age<int> in 18-35
|
||||
|
||||
|
||||
|
||||
需求:需要判断是否是北京身份证(开头为”1100”)。
|
||||
条件表达式:.IdentityCardNumber sw 1100
|
||||
另一种方法:
|
||||
入参使用表达式:@Get .IdentityCardNumber
|
||||
条件表达式:sw 1100
|
||||
|
||||
~~~
|
||||
## 3. 从DLL生成控件的枚举值:
|
||||
* **Action - 动作**
|
||||
* 入参:自定义。如果入参类型为IDynamicContext,会传入当前的上下文;如果入参类型为NodeBase,会传入节点对应的Model。如果不显式指定参数来源,参数会尝试获取运行时上一节点返回值,并根据当前入参类型尝试进行类型转换。
|
||||
* 入参:自定义。如果入参类型为IDynamicContext,会传入当前的上下文;如果入参类型为IFlowNode,会传入节点对应的实体Model。如果不显式指定参数来源,参数会尝试获取运行时上一节点返回值,并根据当前入参类型尝试进行类型转换。
|
||||
* 返回值:自定义,支持异步等待。
|
||||
* 描述:同步执行对应的方法。
|
||||
* **Flipflop - 触发器**
|
||||
* 全局触发器
|
||||
* 入参:依照Action节点。
|
||||
* 返回值:Task`<IFlipflopContext<TResult>>`
|
||||
* 描述:运行开始时,所有无上级节点的触发器节点(在当前分支中作为起始节点),分别建立新的线程运行,然后异步等待触发(如果有)。这种触发器拥有独自的DynamicContext上下文(共用同一个Ioc),执行完成之后,会重新从分支起点的触发器开始等待。
|
||||
* 描述:运行开始时,所有无上级节点的触发器节点(在当前分支中作为起始节点),分别建立新的线程运行,然后异步等待触发(如果有)。这种触发器拥有独自的IDynamicContext上下文(共用同一个Ioc),执行完成之后,会重新从分支起点的触发器开始等待。
|
||||
* 分支中的触发器
|
||||
* 入参:依照Action节点。
|
||||
* 返回值:Task`<IFlipflopContext<TResult>>`
|
||||
|
||||
@@ -1204,7 +1204,7 @@ namespace Serein.Workbench.Views
|
||||
var nodeConotrol = selectNodeControls[0];
|
||||
// 选取了控件
|
||||
flowNodeService.CurrentSelectNodeControl = nodeConotrol; // 更新选取节点显示
|
||||
App.GetService<FlowNodeService>().CurrentMethodDetailsInfo = nodeConotrol.ViewModel.NodeModel.MethodDetails.ToInfo();
|
||||
// App.GetService<FlowNodeService>().CurrentMethodDetailsInfo = nodeConotrol.ViewModel.NodeModel.MethodDetails.ToInfo();
|
||||
// ChangeViewerObjOfNode(selectNodeControls[0]);
|
||||
}
|
||||
|
||||
|
||||
@@ -48,5 +48,22 @@ namespace Serein.Workbench.Views
|
||||
LogWindow.Instance.Close();
|
||||
System.Windows.Application.Current.Shutdown();
|
||||
}
|
||||
|
||||
protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
|
||||
{
|
||||
// 获取当前的焦点控件
|
||||
var element = FocusManager.GetFocusedElement(this);
|
||||
|
||||
// 如果当前有焦点控件,且点击的区域不在该控件上,则清除焦点
|
||||
if (element != null && !element.IsMouseOver)
|
||||
{
|
||||
// 将焦点设置到窗口本身或其他透明控件
|
||||
FocusManager.SetFocusedElement(this, this);
|
||||
}
|
||||
|
||||
// 继续处理默认的鼠标按下事件
|
||||
base.OnPreviewMouseDown(e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user