From 7848af0363d0733fb2f9ddc579c064ca5288f3a6 Mon Sep 17 00:00:00 2001
From: fengjiayi <12821976+ning_xi@user.noreply.gitee.com>
Date: Tue, 27 May 2025 18:32:40 +0800
Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E4=BA=86=E5=A4=9A=E7=94=BB?=
=?UTF-8?q?=E5=B8=83=E4=B8=8B=EF=BC=8C=E8=8A=82=E7=82=B9=E7=9A=84=E5=A4=8D?=
=?UTF-8?q?=E5=88=B6=E7=B2=98=E8=B4=B4=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Library/Api/IFlowEnvironment.cs | 9 +-
Library/Entity/MoveNodeData.cs | 9 +-
Library/Extension/FlowModelExtension.cs | 7 +-
Library/FlowNode/FlowCanvasDetails.cs | 3 +-
Library/FlowNode/MethodDetailsInfo.cs | 2 +-
Library/FlowNode/SereinProjectData.cs | 1 +
Library/Serein.Library.csproj | 1 +
NodeFlow/Env/FlowEnvironment.cs | 149 +++++---
NodeFlow/Env/FlowEnvironmentDecorator.cs | 12 +-
NodeFlow/Env/MsgControllerOfServer.cs | 6 +-
NodeFlow/Env/RemoteFlowEnvironment.cs | 10 +-
NodeFlow/FlowWorkManagement.cs | 21 +-
NodeFlow/FlowWorkOptions.cs | 2 +-
NodeFlow/Tool/NativeDllHelper.cs | 5 +
Workbench/Api/IFlowCanvas.cs | 5 +
Workbench/App.xaml | 2 -
Workbench/App.xaml.cs | 34 +-
Workbench/Customs/FlowMethodInfoListBox.xaml | 14 +-
.../Customs/FlowMethodInfoListBox.xaml.cs | 120 ++++---
Workbench/LogWindow.xaml.cs | 4 +
Workbench/MainWindow.xaml.cs | 31 +-
Workbench/Models/FlowLibraryInfo.cs | 26 +-
Workbench/Models/MoveNodeModel.cs | 18 +
.../Node/Junction/JunctionControlBase.cs | 47 ++-
Workbench/Node/Junction/JunctionData.cs | 4 +-
Workbench/Node/View/ConnectionControl.cs | 5 +-
Workbench/Node/View/DllControlControl.xaml.cs | 36 +-
Workbench/Serein.WorkBench.csproj | 3 +
Workbench/Services/FlowEEForwardingService.cs | 11 +-
Workbench/Services/FlowNodeService.cs | 202 ++++++++++-
Workbench/Services/KeyEventService.cs | 59 +--
Workbench/Services/NodeControlService.cs | 55 ---
Workbench/Services/WorkbenchEventService.cs | 105 +++++-
.../Themes/NodeTreeItemViewControl.xaml.cs | 7 +-
Workbench/Themes/ObjectViewerControl.xaml.cs | 3 +-
Workbench/Themes/TypeViewerWindow.xaml.cs | 7 +-
Workbench/Tool/WpfFuncTool.cs | 48 +++
Workbench/ViewModels/FlowCanvasViewModel.cs | 4 +-
Workbench/ViewModels/FlowEditViewModel.cs | 13 +-
Workbench/ViewModels/FlowLibrarysViewModel.cs | 27 +-
.../ViewModels/FlowWorkbenchViewModel.cs | 27 +-
Workbench/ViewModels/MainMenuBarViewModel.cs | 32 +-
Workbench/ViewModels/MainViewModel.cs | 10 +-
Workbench/Views/BaseNodesView.xaml.cs | 1 +
Workbench/Views/FlowCanvasView.xaml | 2 +-
Workbench/Views/FlowCanvasView.xaml.cs | 338 +++++++++++++-----
Workbench/Views/FlowEditView.xaml | 6 +-
Workbench/Views/FlowEditView.xaml.cs | 5 +-
Workbench/Views/FlowLibrarysView.xaml | 78 ++--
Workbench/Views/FlowLibrarysView.xaml.cs | 25 +-
Workbench/Views/FlowWorkbenchView.xaml | 12 +-
Workbench/Views/FlowWorkbenchView.xaml.cs | 8 +
Workbench/Views/MainMenuBarView.xaml | 15 +-
53 files changed, 1187 insertions(+), 499 deletions(-)
create mode 100644 Workbench/Models/MoveNodeModel.cs
delete mode 100644 Workbench/Services/NodeControlService.cs
create mode 100644 Workbench/Tool/WpfFuncTool.cs
diff --git a/Library/Api/IFlowEnvironment.cs b/Library/Api/IFlowEnvironment.cs
index 75e6bb6..6debb1e 100644
--- a/Library/Api/IFlowEnvironment.cs
+++ b/Library/Api/IFlowEnvironment.cs
@@ -1097,16 +1097,19 @@ namespace Serein.Library.Api
void SetUIContextOperation(UIContextOperation uiContextOperation);
///
- /// 开始运行
+ /// 开始运行流程
///
- Task StartFlowAsync();
+ /// 需要运行的流程Guid
+ ///
+ Task StartFlowAsync(string[] canvasGuids);
+
///
/// 从选定的节点开始运行
///
///
///
- Task StartAsyncInSelectNode(string startNodeGuid);
+ Task StartFlowFromSelectNodeAsync(string startNodeGuid);
///
/// 结束运行
diff --git a/Library/Entity/MoveNodeData.cs b/Library/Entity/MoveNodeData.cs
index bfac713..d437aa3 100644
--- a/Library/Entity/MoveNodeData.cs
+++ b/Library/Entity/MoveNodeData.cs
@@ -7,12 +7,5 @@ using System.Threading.Tasks;
namespace Serein.Library
{
- ///
- /// 拖拽创建节点使用的数据
- ///
- public class MoveNodeData
- {
- public NodeControlType NodeControlType { get; set; }
- public MethodDetailsInfo MethodDetailsInfo { get; set; }
- }
+
}
diff --git a/Library/Extension/FlowModelExtension.cs b/Library/Extension/FlowModelExtension.cs
index df53097..6e051d6 100644
--- a/Library/Extension/FlowModelExtension.cs
+++ b/Library/Extension/FlowModelExtension.cs
@@ -101,10 +101,10 @@ namespace Serein.Library
// 生成参数列表
ParameterData[] parameterData = nodeModel.SaveParameterInfo();
- NodeInfo nodeInfo = new NodeInfo
+ var nodeInfo = new NodeInfo
{
- Guid = nodeModel.Guid,
CanvasGuid = nodeModel.CanvasGuid,
+ Guid = nodeModel.Guid,
AssemblyName = nodeModel.MethodDetails.AssemblyName,
MethodName = nodeModel.MethodDetails?.MethodName,
Label = nodeModel.MethodDetails?.MethodAnotherName,
@@ -130,10 +130,12 @@ namespace Serein.Library
///
/// 从节点信息加载节点
///
+ ///
///
///
public static void LoadInfo(this NodeModelBase nodeModel, NodeInfo nodeInfo)
{
+ nodeModel.CanvasGuid = nodeInfo.CanvasGuid;
nodeModel.Guid = nodeInfo.Guid;
nodeModel.Position = nodeInfo.Position ?? new PositionOfUI(0, 0);// 加载位置信息
var md = nodeModel.MethodDetails; // 当前节点的方法说明
@@ -191,6 +193,7 @@ namespace Serein.Library
///
/// 开始执行
///
+ ///
///
/// 流程运行
///
diff --git a/Library/FlowNode/FlowCanvasDetails.cs b/Library/FlowNode/FlowCanvasDetails.cs
index 4f56a64..0fa1ef7 100644
--- a/Library/FlowNode/FlowCanvasDetails.cs
+++ b/Library/FlowNode/FlowCanvasDetails.cs
@@ -23,6 +23,7 @@ namespace Serein.Library
Env = env;
}
+
public IFlowEnvironment Env { get; }
///
@@ -79,8 +80,6 @@ namespace Serein.Library
///
private string _startNode;
-
-
}
diff --git a/Library/FlowNode/MethodDetailsInfo.cs b/Library/FlowNode/MethodDetailsInfo.cs
index 64bb13f..e8856fb 100644
--- a/Library/FlowNode/MethodDetailsInfo.cs
+++ b/Library/FlowNode/MethodDetailsInfo.cs
@@ -27,7 +27,7 @@ namespace Serein.Library
public string NodeType { get; set; }
///
- /// 方法说明
+ /// 方法别名
///
public string MethodAnotherName { get; set; }
diff --git a/Library/FlowNode/SereinProjectData.cs b/Library/FlowNode/SereinProjectData.cs
index 8ccc9fa..3cd8754 100644
--- a/Library/FlowNode/SereinProjectData.cs
+++ b/Library/FlowNode/SereinProjectData.cs
@@ -336,6 +336,7 @@ namespace Serein.Library
_x = x; _y = y;
}
+
///
/// 指示控件在画布的横向向方向上的位置
///
diff --git a/Library/Serein.Library.csproj b/Library/Serein.Library.csproj
index b0f5275..574d076 100644
--- a/Library/Serein.Library.csproj
+++ b/Library/Serein.Library.csproj
@@ -14,6 +14,7 @@
MIT
True
latest
+ no
true
true
diff --git a/NodeFlow/Env/FlowEnvironment.cs b/NodeFlow/Env/FlowEnvironment.cs
index 79265f3..1c84fb0 100644
--- a/NodeFlow/Env/FlowEnvironment.cs
+++ b/NodeFlow/Env/FlowEnvironment.cs
@@ -368,27 +368,87 @@ namespace Serein.NodeFlow.Env
/// 异步运行
///
///
- public async Task StartFlowAsync()
+ public async Task StartFlowAsync(string[] canvasGuids)
{
+ #region 校验参数
+ HashSet guids = new HashSet();
+ bool isBreak = false;
+ foreach (var canvasGuid in canvasGuids)
+ {
+ if (guids.Contains(canvasGuid))
+ {
+ SereinEnv.WriteLine(InfoType.WARN, $"画布重复,停止运行。{canvasGuid}");
+ isBreak = true;
+ }
+ if (!FlowCanvass.ContainsKey(canvasGuid))
+ {
+ SereinEnv.WriteLine(InfoType.WARN, $"画布不存在,停止运行。{canvasGuid}");
+ isBreak = true;
+ }
+ var count = NodeModels.Values.Count(n => n.CanvasGuid.Equals(canvasGuid));
+ if(count == 0)
+ {
+ SereinEnv.WriteLine(InfoType.WARN, $"画布没有节点,停止运行。{canvasGuid}");
+ isBreak = true;
+ }
+ else
+ {
+ guids.Add(canvasGuid);
+ }
+ }
+ if (isBreak)
+ {
+ guids.Clear();
+ return false;
+ }
+ #endregion
+
+
+ #region 初始化每个画布的数据,转换为流程任务
+ Dictionary flowTasks = [];
+ foreach (var guid in guids)
+ {
+ if (!TryGetCanvasModel(guid, out var canvasModel))
+ {
+ SereinEnv.WriteLine(InfoType.WARN, $"画布不存在,停止运行。{guid}");
+ return false;
+ }
+ var ft = new FlowTask();
+ ft.GetNodes = () => NodeModels.Values.Where(node => node.CanvasGuid.Equals(guid)).ToList();
+ var startNodeModel = NodeModels.GetValueOrDefault(canvasModel.StartNode);
+ if(startNodeModel is null)
+ {
+ SereinEnv.WriteLine(InfoType.WARN, $"画布不存在起始节点,将停止运行。{guid}");
+ return false;
+ }
+ ft.GetStartNode = () => startNodeModel;
+ flowTasks.Add(guid, ft);
+ }
+ #endregion
+
+
+
IOC.Reset();
IOC.Register(); // 注册脚本接口
var flowTaskOptions = new FlowWorkOptions
{
- Environment = this,
- FlowContextPool = new ObjectPool(() => new DynamicContext(this)),
- //Nodes = NodeModels.Values.ToList(),
- AutoRegisterTypes = this.FlowLibraryManagement.GetaAutoRegisterType(),
- InitMds = this.FlowLibraryManagement.GetMdsOnFlowStart(NodeType.Init),
+ Environment = this, // 流程
+ Flows = flowTasks,
+ FlowContextPool = new ObjectPool(() => new DynamicContext(this)), // 上下文对象池
+ AutoRegisterTypes = this.FlowLibraryManagement.GetaAutoRegisterType(), // 需要自动实例化的类型
+ InitMds = this.FlowLibraryManagement.GetMdsOnFlowStart(NodeType.Init),
LoadMds = this.FlowLibraryManagement.GetMdsOnFlowStart(NodeType.Loading),
ExitMds = this.FlowLibraryManagement.GetMdsOnFlowStart(NodeType.Exit),
-
};
+
+
+
flowTaskManagement = new FlowWorkManagement(flowTaskOptions);
var cts = new CancellationTokenSource();
try
{
- var t =await flowTaskManagement.RunAsync(cts.Token);
+ var t = await flowTaskManagement.RunAsync(cts.Token);
}
catch (Exception ex)
{
@@ -405,12 +465,13 @@ namespace Serein.NodeFlow.Env
}
+
///
/// 从选定节点开始运行
///
///
///
- public async Task StartAsyncInSelectNode(string startNodeGuid)
+ public async Task StartFlowFromSelectNodeAsync(string startNodeGuid)
{
if (flowTaskManagement is null)
@@ -425,12 +486,6 @@ namespace Serein.NodeFlow.Env
{
return false;
}
- //var getExp = "@get .DebugSetting.IsEnable";
- //var getExpResult1 = SerinExpressionEvaluator.Evaluate(getExp, nodeModel,out _);
- //var setExp = "@set .DebugSetting.IsEnable = false";
- //SerinExpressionEvaluator.Evaluate(setExp, nodeModel,out _);
- //var getExpResult2 = SerinExpressionEvaluator.Evaluate(getExp, nodeModel, out _);
-
await flowTaskManagement.StartFlowInSelectNodeAsync(this, nodeModel);
return true;
}
@@ -559,9 +614,22 @@ namespace Serein.NodeFlow.Env
LoadLibrary(dllFilePath); // 加载项目文件时加载对应的程序集
}
+
+
_ = Task.Run( async () =>
- {
+ {
+ // 加载画布
+ foreach (var canvasInfo in projectData.Canvass)
+ {
+ LoadCanvas(canvasInfo);
+ }
await LoadNodeInfosAsync(projectData.Nodes.ToList()); // 加载节点信息
+
+ // 加载画布
+ foreach (var canvasInfo in projectData.Canvass)
+ {
+ await SetStartNodeAsync(canvasInfo.Guid, canvasInfo.StartNode); // 设置起始节点
+ }
//await SetStartNodeAsync("", projectData.StartNode); // 设置起始节点
});
@@ -779,20 +847,31 @@ namespace Serein.NodeFlow.Env
///
public async Task CreateCanvasAsync(string canvasName, int width, int height)
{
- var model = new FlowCanvasDetails(this)
+ var info = new FlowCanvasDetailsInfo()
{
Guid = Guid.NewGuid().ToString(),
Height = height,
Width = width,
+ ViewX = 0,
+ ViewY = 0,
+ ScaleY = 1,
+ ScaleX = 1,
Name = !string.IsNullOrWhiteSpace(canvasName) ? canvasName : $"流程图{_addCanvasCount++}",
};
+ var model = LoadCanvas(info);
+ return info;
+ }
+
+ private FlowCanvasDetails LoadCanvas(FlowCanvasDetailsInfo info)
+ {
+ var model = new FlowCanvasDetails(this);
+ model.LoadInfo(info);
FlowCanvass.Add(model.Guid, model);
- await UIContextOperation.InvokeAsync(() =>
+ UIContextOperation.InvokeAsync(() =>
{
OnCanvasCreate.Invoke(new CanvasCreateEventArgs(model));
});
- var info = model.ToInfo();
- return info;
+ return model;
}
///
@@ -957,7 +1036,7 @@ namespace Serein.NodeFlow.Env
#region 确定节点之间的参数调用关系
foreach (var toNode in NodeModels.Values)
{
- var canvasGuid = toNode.Guid;
+ var canvasGuid = toNode.CanvasGuid;
if (toNode.MethodDetails.ParameterDetailss == null)
{
continue;
@@ -1727,7 +1806,7 @@ namespace Serein.NodeFlow.Env
private bool TryAddNode(NodeModelBase nodeModel)
{
nodeModel.Guid ??= Guid.NewGuid().ToString();
- NodeModels[nodeModel.Guid] = nodeModel;
+ NodeModels.TryAdd(nodeModel.Guid, nodeModel);
// 如果是触发器,则需要添加到专属集合中
if (nodeModel is SingleFlipflopNode flipflopNode)
@@ -1944,32 +2023,22 @@ namespace Serein.NodeFlow.Env
///
/// 更改起点节点
///
- ///
- ///
+ /// 节点所在的画布
+ /// 起始节点
private void SetStartNode(FlowCanvasDetails cavnasModel, NodeModelBase newStartNode)
{
var oldNodeGuid = cavnasModel.StartNode;
+ /*if(TryGetNodeModel(oldNodeGuid, out var newStartNodeModel))
+ {
+ newStartNode.IsStart = false;
+ }*/
cavnasModel.StartNode = newStartNode.Guid;
+ //newStartNode.IsStart = true;
+
UIContextOperation?.Invoke(() => OnStartNodeChange?.Invoke(new StartNodeChangeEventArgs(cavnasModel.Guid, oldNodeGuid, cavnasModel.StartNode)));
- //if (OperatingSystem.IsWindows())
- //{
- // }
}
- /////
- ///// 输出内容
- /////
- /////
- //private void Output(string msg)
- //{
- // if (OperatingSystem.IsWindows())
- // {
- // UIContextOperation?.Invoke(() => OnEnvOut?.Invoke(msg));
- // }
-
- //}
-
///
/// 向容器登记缓存的持久化实例
///
diff --git a/NodeFlow/Env/FlowEnvironmentDecorator.cs b/NodeFlow/Env/FlowEnvironmentDecorator.cs
index 5456d7c..4d6493f 100644
--- a/NodeFlow/Env/FlowEnvironmentDecorator.cs
+++ b/NodeFlow/Env/FlowEnvironmentDecorator.cs
@@ -263,7 +263,7 @@ namespace Serein.NodeFlow.Env
/// 目标节点控制点
/// 决定了方法执行后的后继行为
public async Task ConnectInvokeNodeAsync(string canvasGuid,
- string fromNodeGuid,
+ string fromNodeGuid,
string toNodeGuid,
JunctionType fromNodeJunctionType,
JunctionType toNodeJunctionType,
@@ -518,14 +518,16 @@ namespace Serein.NodeFlow.Env
return await currentFlowEnvironment.SetStartNodeAsync(canvasGuid, nodeGuid);
}
- public async Task StartFlowAsync()
+ public async Task StartFlowAsync(string[] canvasGuids)
{
- return await currentFlowEnvironment.StartFlowAsync();
+ return await currentFlowEnvironment.StartFlowAsync(canvasGuids);
}
- public async Task StartAsyncInSelectNode(string startNodeGuid)
+
+
+ public async Task StartFlowFromSelectNodeAsync(string startNodeGuid)
{
- return await currentFlowEnvironment.StartAsyncInSelectNode(startNodeGuid);
+ return await currentFlowEnvironment.StartFlowFromSelectNodeAsync(startNodeGuid);
}
diff --git a/NodeFlow/Env/MsgControllerOfServer.cs b/NodeFlow/Env/MsgControllerOfServer.cs
index 5902b98..005fce0 100644
--- a/NodeFlow/Env/MsgControllerOfServer.cs
+++ b/NodeFlow/Env/MsgControllerOfServer.cs
@@ -173,10 +173,10 @@ namespace Serein.NodeFlow.Env
///
///
[AutoSocketHandle(ThemeValue = EnvMsgTheme.StartFlow)]
- private async Task