mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-05-04 06:11:28 +08:00
新增了上游节点类型:执行下一节点之前,调用上一节点的上游分支。
修正了WAT中的错误,现在可以自动化处理了。
This commit is contained in:
@@ -106,7 +106,6 @@ namespace DynamicDemo.Node
|
|||||||
}).ToArray();
|
}).ToArray();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await Task.WhenAll([startNode.ExecuteStack(context),.. tasks]);
|
await Task.WhenAll([startNode.ExecuteStack(context),.. tasks]);
|
||||||
@@ -138,11 +137,9 @@ namespace DynamicDemo.Node
|
|||||||
object?[]? parameters = singleFlipFlopNode.GetParameters(context, md);
|
object?[]? parameters = singleFlipFlopNode.GetParameters(context, md);
|
||||||
// 调用委托并获取结果
|
// 调用委托并获取结果
|
||||||
|
|
||||||
|
|
||||||
FlipflopContext flipflopContext = await func.Invoke(md.ActingInstance, parameters);
|
FlipflopContext flipflopContext = await func.Invoke(md.ActingInstance, parameters);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (flipflopContext == null)
|
if (flipflopContext == null)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
@@ -155,7 +152,7 @@ namespace DynamicDemo.Node
|
|||||||
{
|
{
|
||||||
singleFlipFlopNode.FlowState = true;
|
singleFlipFlopNode.FlowState = true;
|
||||||
singleFlipFlopNode.FlowData = flipflopContext.Data;
|
singleFlipFlopNode.FlowData = flipflopContext.Data;
|
||||||
var tasks = singleFlipFlopNode.TrueBranch.Select(nextNode =>
|
var tasks = singleFlipFlopNode.SucceedBranch.Select(nextNode =>
|
||||||
{
|
{
|
||||||
var context = new DynamicContext(ServiceContainer);
|
var context = new DynamicContext(ServiceContainer);
|
||||||
nextNode.PreviousNode = singleFlipFlopNode;
|
nextNode.PreviousNode = singleFlipFlopNode;
|
||||||
|
|||||||
@@ -13,9 +13,22 @@ namespace Serein.DynamicFlow.NodeModel
|
|||||||
|
|
||||||
public enum ConnectionType
|
public enum ConnectionType
|
||||||
{
|
{
|
||||||
IsTrue,
|
/// <summary>
|
||||||
IsFalse,
|
/// 真分支
|
||||||
IsEx,
|
/// </summary>
|
||||||
|
IsSucceed,
|
||||||
|
/// <summary>
|
||||||
|
/// 假分支
|
||||||
|
/// </summary>
|
||||||
|
IsFail,
|
||||||
|
/// <summary>
|
||||||
|
/// 异常发生分支
|
||||||
|
/// </summary>
|
||||||
|
IsError,
|
||||||
|
/// <summary>
|
||||||
|
/// 上游分支(执行当前节点前会执行一次上游分支)
|
||||||
|
/// </summary>
|
||||||
|
Upstream,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -49,16 +62,19 @@ namespace Serein.DynamicFlow.NodeModel
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 下一节点集合(真分支)
|
/// 下一节点集合(真分支)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<NodeBase> TrueBranch { get; set; } = [];
|
public List<NodeBase> SucceedBranch { get; set; } = [];
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 下一节点集合(假分支)
|
/// 下一节点集合(假分支)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<NodeBase> FalseBranch { get; set; } = [];
|
public List<NodeBase> FailBranch { get; set; } = [];
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 异常分支
|
/// 异常分支
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<NodeBase> ExBranch { get; set; } = [];
|
public List<NodeBase> ErrorBranch { get; set; } = [];
|
||||||
|
/// <summary>
|
||||||
|
/// 上游分支
|
||||||
|
/// </summary>
|
||||||
|
public List<NodeBase> UpstreamBranch { get; set; } = [];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 当前状态(进入真分支还是假分支,异常分支在异常中确定)
|
/// 当前状态(进入真分支还是假分支,异常分支在异常中确定)
|
||||||
@@ -95,16 +111,10 @@ namespace Serein.DynamicFlow.NodeModel
|
|||||||
object?[]? parameters = GetParameters(context, MethodDetails);
|
object?[]? parameters = GetParameters(context, MethodDetails);
|
||||||
if (md.ReturnType == typeof(void))
|
if (md.ReturnType == typeof(void))
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
((Action<object, object[]>)del).Invoke(md.ActingInstance, parameters);
|
((Action<object, object[]>)del).Invoke(md.ActingInstance, parameters);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
result = ((Func<object, object[], object>)del).Invoke(md.ActingInstance, parameters);
|
result = ((Func<object, object[], object>)del).Invoke(md.ActingInstance, parameters);
|
||||||
|
|
||||||
|
|
||||||
@@ -173,16 +183,20 @@ namespace Serein.DynamicFlow.NodeModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// context.SetFlowData(result);
|
|
||||||
// CurrentData = result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public async Task ExecuteStack(DynamicContext context)
|
public async Task ExecuteStack(DynamicContext context)
|
||||||
|
{
|
||||||
|
await Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await ExecuteStackTmp(context);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ExecuteStackTmp(DynamicContext context)
|
||||||
{
|
{
|
||||||
var cts = context.ServiceContainer.Get<CancellationTokenSource>();
|
var cts = context.ServiceContainer.Get<CancellationTokenSource>();
|
||||||
|
|
||||||
@@ -191,19 +205,23 @@ namespace Serein.DynamicFlow.NodeModel
|
|||||||
|
|
||||||
while (stack.Count > 0 && !cts.IsCancellationRequested) // 循环中直到栈为空才会退出循环
|
while (stack.Count > 0 && !cts.IsCancellationRequested) // 循环中直到栈为空才会退出循环
|
||||||
{
|
{
|
||||||
|
|
||||||
// 从栈中弹出一个节点作为当前节点进行处理
|
// 从栈中弹出一个节点作为当前节点进行处理
|
||||||
var currentNode = stack.Pop();
|
var currentNode = stack.Pop();
|
||||||
|
|
||||||
//currentNode.MethodDetails.ActingInstance ??= context.ServiceContainer.Get(
|
|
||||||
// currentNode.MethodDetails.ActingInstanceType
|
|
||||||
// );
|
|
||||||
|
|
||||||
if (currentNode.MethodDetails != null)
|
if (currentNode.MethodDetails != null)
|
||||||
{
|
{
|
||||||
currentNode.MethodDetails.ActingInstance ??= context.ServiceContainer.Get(MethodDetails.ActingInstanceType);
|
currentNode.MethodDetails.ActingInstance ??= context.ServiceContainer.Get(MethodDetails.ActingInstanceType);
|
||||||
|
} // 设置方法执行的对象
|
||||||
|
|
||||||
|
// 获取上游分支,首先执行一次
|
||||||
|
var upstreamNodes = currentNode.UpstreamBranch;
|
||||||
|
for (int i = upstreamNodes.Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
upstreamNodes[i].PreviousNode = currentNode;
|
||||||
|
await upstreamNodes[i].ExecuteStack(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (currentNode.MethodDetails != null && currentNode.MethodDetails.MethodDynamicType == DynamicNodeType.Flipflop)
|
if (currentNode.MethodDetails != null && currentNode.MethodDetails.MethodDynamicType == DynamicNodeType.Flipflop)
|
||||||
{
|
{
|
||||||
currentNode.FlowData = await currentNode.ExecuteAsync(context);
|
currentNode.FlowData = await currentNode.ExecuteAsync(context);
|
||||||
@@ -214,8 +232,8 @@ namespace Serein.DynamicFlow.NodeModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var nextNodes = currentNode.FlowState ? currentNode.TrueBranch
|
var nextNodes = currentNode.FlowState ? currentNode.SucceedBranch
|
||||||
: currentNode.FalseBranch;
|
: currentNode.FailBranch;
|
||||||
|
|
||||||
// 将下一个节点集合中的所有节点逆序推入栈中
|
// 将下一个节点集合中的所有节点逆序推入栈中
|
||||||
for (int i = nextNodes.Count - 1; i >= 0; i--)
|
for (int i = nextNodes.Count - 1; i >= 0; i--)
|
||||||
@@ -243,6 +261,9 @@ namespace Serein.DynamicFlow.NodeModel
|
|||||||
|
|
||||||
var mdEd = md.ExplicitDatas[i];
|
var mdEd = md.ExplicitDatas[i];
|
||||||
Type type = mdEd.DataType;
|
Type type = mdEd.DataType;
|
||||||
|
|
||||||
|
var f1 = PreviousNode?.FlowData?.GetType();
|
||||||
|
var f2 = mdEd.DataType;
|
||||||
if (type == typeof(DynamicContext))
|
if (type == typeof(DynamicContext))
|
||||||
{
|
{
|
||||||
parameters[i] = context;
|
parameters[i] = context;
|
||||||
@@ -280,17 +301,19 @@ namespace Serein.DynamicFlow.NodeModel
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
parameters[i] = "";
|
||||||
|
|
||||||
|
//parameters[i] = ConvertValue(mdEd.DataValue, mdEd.ExplicitType);
|
||||||
parameters[i] = ConvertValue(mdEd.DataValue, mdEd.ExplicitType);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if ((f1 != null && f2 != null) && f2.IsAssignableFrom(f1) || f2.FullName.Equals(f1.FullName))
|
||||||
|
{
|
||||||
|
parameters[i] = PreviousNode?.FlowData;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
//var tmpParameter = context.GetFlowData()?.ToString();
|
|
||||||
var tmpParameter = PreviousNode?.FlowData?.ToString();
|
var tmpParameter = PreviousNode?.FlowData?.ToString();
|
||||||
if (mdEd.DataType.IsEnum)
|
if (mdEd.DataType.IsEnum)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ namespace Serein.Module
|
|||||||
public void Wait([Explicit]int time = 1000)
|
public void Wait([Explicit]int time = 1000)
|
||||||
{
|
{
|
||||||
Thread.Sleep(time);
|
Thread.Sleep(time);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodDetail(DynamicNodeType.Action,"启动浏览器")]
|
[MethodDetail(DynamicNodeType.Action,"启动浏览器")]
|
||||||
@@ -145,7 +146,7 @@ namespace Serein.Module
|
|||||||
|
|
||||||
|
|
||||||
[MethodDetail(DynamicNodeType.Action,"定位元素")]
|
[MethodDetail(DynamicNodeType.Action,"定位元素")]
|
||||||
public IWebElement FindElement(string key, [Explicit] ByType byType = ByType.Id, [Explicit] int index = 0)
|
public IWebElement FindElement([Explicit] string key = "", [Explicit] ByType byType = ByType.XPath, [Explicit] int index = 0)
|
||||||
{
|
{
|
||||||
By by = byType switch
|
By by = byType switch
|
||||||
{
|
{
|
||||||
@@ -176,6 +177,8 @@ namespace Serein.Module
|
|||||||
actions.ContextClick(element).Perform();
|
actions.ContextClick(element).Perform();
|
||||||
break;
|
break;
|
||||||
case ActionType.SendKeys:
|
case ActionType.SendKeys:
|
||||||
|
element.Click();
|
||||||
|
element.Clear();
|
||||||
element.SendKeys(text);
|
element.SendKeys(text);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,13 +157,13 @@ namespace Serein.WorkBench
|
|||||||
Shutdown(); // 关闭应用程序
|
Shutdown(); // 关闭应用程序
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//else if(1 == 1)
|
else if (1 == 1)
|
||||||
//{
|
{
|
||||||
// string filePath =@"F:\临时\project\project.dnf";
|
string filePath = @"F:\临时\project\project.dnf";
|
||||||
// string content = System.IO.File.ReadAllText(filePath); // 读取整个文件内容
|
string content = System.IO.File.ReadAllText(filePath); // 读取整个文件内容
|
||||||
// FData = JsonConvert.DeserializeObject<SereinOutputFileData>(content);
|
FData = JsonConvert.DeserializeObject<SereinOutputFileData>(content);
|
||||||
// App.FileDataPath = System.IO.Path.GetDirectoryName(filePath);
|
App.FileDataPath = System.IO.Path.GetDirectoryName(filePath);
|
||||||
//}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ using System.Windows.Shapes;
|
|||||||
using static Serein.WorkBench.Connection;
|
using static Serein.WorkBench.Connection;
|
||||||
using DynamicDemo.Node;
|
using DynamicDemo.Node;
|
||||||
using Npgsql.Logging;
|
using Npgsql.Logging;
|
||||||
|
using System.Threading.Tasks.Dataflow;
|
||||||
|
|
||||||
namespace Serein.WorkBench
|
namespace Serein.WorkBench
|
||||||
{
|
{
|
||||||
@@ -38,8 +39,6 @@ namespace Serein.WorkBench
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class Connection
|
public class Connection
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
public required NodeControlBase Start { get; set; } // 起始TextBlock
|
public required NodeControlBase Start { get; set; } // 起始TextBlock
|
||||||
public required NodeControlBase End { get; set; } // 结束TextBlock
|
public required NodeControlBase End { get; set; } // 结束TextBlock
|
||||||
public required Line Line { get; set; } // 连接的线
|
public required Line Line { get; set; } // 连接的线
|
||||||
@@ -79,9 +78,10 @@ namespace Serein.WorkBench
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 设置线条的样式
|
// 设置线条的样式
|
||||||
Line.Stroke = Type == ConnectionType.IsTrue ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#04FC10"))
|
Line.Stroke = Type == ConnectionType.IsSucceed ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#04FC10"))
|
||||||
: Type == ConnectionType.IsFalse ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#F18905"))
|
: Type == ConnectionType.IsFail ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#F18905"))
|
||||||
: new SolidColorBrush((Color)ColorConverter.ConvertFromString("#AB616B"));
|
: Type == ConnectionType.IsError ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#AB616B"))
|
||||||
|
: new SolidColorBrush((Color)ColorConverter.ConvertFromString("#4A82E4"));
|
||||||
Line.StrokeDashArray = [dashLength, dashLength];
|
Line.StrokeDashArray = [dashLength, dashLength];
|
||||||
|
|
||||||
// 创建新的 Storyboard
|
// 创建新的 Storyboard
|
||||||
@@ -102,9 +102,10 @@ namespace Serein.WorkBench
|
|||||||
if (_animationStoryboard != null)
|
if (_animationStoryboard != null)
|
||||||
{
|
{
|
||||||
_animationStoryboard.Stop();
|
_animationStoryboard.Stop();
|
||||||
Line.Stroke = Type == ConnectionType.IsTrue ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#04FC10"))
|
Line.Stroke = Type == ConnectionType.IsSucceed ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#04FC10"))
|
||||||
: Type == ConnectionType.IsFalse ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#F18905"))
|
: Type == ConnectionType.IsFail ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#F18905"))
|
||||||
: new SolidColorBrush((Color)ColorConverter.ConvertFromString("#AB616B"));
|
: Type == ConnectionType.IsError ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#AB616B"))
|
||||||
|
: new SolidColorBrush((Color)ColorConverter.ConvertFromString("#4A82E4"));
|
||||||
Line.StrokeDashArray = null;
|
Line.StrokeDashArray = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -339,8 +340,10 @@ namespace Serein.WorkBench
|
|||||||
{
|
{
|
||||||
if (nodeControls.TryGetValue(node.guid, out var fromNode))
|
if (nodeControls.TryGetValue(node.guid, out var fromNode))
|
||||||
{
|
{
|
||||||
ConnectNodeControlChildren(fromNode, node.trueNodes, nodeControls, ConnectionType.IsTrue);
|
ConnectNodeControlChildren(fromNode, node.trueNodes, nodeControls, ConnectionType.IsSucceed);
|
||||||
ConnectNodeControlChildren(fromNode, node.falseNodes, nodeControls, ConnectionType.IsFalse);
|
ConnectNodeControlChildren(fromNode, node.falseNodes, nodeControls, ConnectionType.IsFail);
|
||||||
|
//ConnectNodeControlChildren(fromNode, node.errorNodes, nodeControls, ConnectionType.IsError);
|
||||||
|
ConnectNodeControlChildren(fromNode, node.upstreamNodes, nodeControls, ConnectionType.Upstream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -380,9 +383,10 @@ namespace Serein.WorkBench
|
|||||||
{
|
{
|
||||||
|
|
||||||
IsHitTestVisible = true,
|
IsHitTestVisible = true,
|
||||||
Stroke = connectionType == ConnectionType.IsTrue ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#04FC10"))
|
Stroke = connectionType == ConnectionType.IsSucceed ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#04FC10"))
|
||||||
: connectionType == ConnectionType.IsFalse ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#F18905"))
|
: connectionType == ConnectionType.IsFail ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#F18905"))
|
||||||
: new SolidColorBrush((Color)ColorConverter.ConvertFromString("#AB616B")),
|
: connectionType == ConnectionType.IsError ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#AB616B"))
|
||||||
|
: new SolidColorBrush((Color)ColorConverter.ConvertFromString("#4A82E4")),
|
||||||
|
|
||||||
StrokeThickness = 2,
|
StrokeThickness = 2,
|
||||||
X1 = Canvas.GetLeft(fromNode) + fromNode.ActualWidth / 2,
|
X1 = Canvas.GetLeft(fromNode) + fromNode.ActualWidth / 2,
|
||||||
@@ -394,17 +398,21 @@ namespace Serein.WorkBench
|
|||||||
ConfigureLineContextMenu(line);
|
ConfigureLineContextMenu(line);
|
||||||
FlowChartCanvas.Children.Add(line);
|
FlowChartCanvas.Children.Add(line);
|
||||||
|
|
||||||
if (connectionType == ConnectionType.IsTrue)
|
if (connectionType == ConnectionType.IsSucceed)
|
||||||
{
|
{
|
||||||
fromNode.Node.TrueBranch.Add(toNode.Node);
|
fromNode.Node.SucceedBranch.Add(toNode.Node);
|
||||||
}
|
}
|
||||||
else if (connectionType == ConnectionType.IsFalse)
|
else if (connectionType == ConnectionType.IsFail)
|
||||||
{
|
{
|
||||||
fromNode.Node.FalseBranch.Add(toNode.Node);
|
fromNode.Node.FailBranch.Add(toNode.Node);
|
||||||
}
|
}
|
||||||
else if (connectionType == ConnectionType.IsEx)
|
else if (connectionType == ConnectionType.IsError)
|
||||||
{
|
{
|
||||||
fromNode.Node.ExBranch.Add(toNode.Node);
|
fromNode.Node.ErrorBranch.Add(toNode.Node);
|
||||||
|
}
|
||||||
|
else if (connectionType == ConnectionType.Upstream)
|
||||||
|
{
|
||||||
|
fromNode.Node.UpstreamBranch.Add(toNode.Node);
|
||||||
}
|
}
|
||||||
|
|
||||||
toNode.Node.PreviousNodes.Add(fromNode.Node);
|
toNode.Node.PreviousNodes.Add(fromNode.Node);
|
||||||
@@ -564,17 +572,20 @@ namespace Serein.WorkBench
|
|||||||
private void ConfigureContextMenu(NodeControlBase nodeControl)
|
private void ConfigureContextMenu(NodeControlBase nodeControl)
|
||||||
{
|
{
|
||||||
var contextMenu = new ContextMenu();
|
var contextMenu = new ContextMenu();
|
||||||
contextMenu.Items.Add(CreateMenuItem("查看返回类型", (s, e) =>
|
|
||||||
|
if (nodeControl.Node?.MethodDetails?.ReturnType is Type returnType && returnType != typeof(void))
|
||||||
{
|
{
|
||||||
if (nodeControl.Node?.MethodDetails?.ReturnType is Type returnType && returnType != typeof(void))
|
contextMenu.Items.Add(CreateMenuItem("查看返回类型", (s, e) =>
|
||||||
{
|
{
|
||||||
DisplayReturnTypeTreeViewer(returnType);
|
DisplayReturnTypeTreeViewer(returnType);
|
||||||
}
|
}));
|
||||||
}));
|
}
|
||||||
contextMenu.Items.Add(CreateMenuItem("设为起点", (s, e) => SetIsStartBlock(nodeControl)));
|
contextMenu.Items.Add(CreateMenuItem("设为起点", (s, e) => SetIsStartBlock(nodeControl)));
|
||||||
contextMenu.Items.Add(CreateMenuItem("删除", (s, e) => DeleteBlock(nodeControl)));
|
contextMenu.Items.Add(CreateMenuItem("删除", (s, e) => DeleteBlock(nodeControl)));
|
||||||
contextMenu.Items.Add(CreateMenuItem("添加 真分支", (s, e) => StartConnection(nodeControl, ConnectionType.IsTrue)));
|
contextMenu.Items.Add(CreateMenuItem("添加 真分支", (s, e) => StartConnection(nodeControl, ConnectionType.IsSucceed)));
|
||||||
contextMenu.Items.Add(CreateMenuItem("添加 假分支", (s, e) => StartConnection(nodeControl, ConnectionType.IsFalse)));
|
contextMenu.Items.Add(CreateMenuItem("添加 假分支", (s, e) => StartConnection(nodeControl, ConnectionType.IsFail)));
|
||||||
|
contextMenu.Items.Add(CreateMenuItem("添加 异常分支", (s, e) => StartConnection(nodeControl, ConnectionType.IsError)));
|
||||||
|
contextMenu.Items.Add(CreateMenuItem("添加 上游分支", (s, e) => StartConnection(nodeControl, ConnectionType.Upstream)));
|
||||||
|
|
||||||
nodeControl.ContextMenu = contextMenu;
|
nodeControl.ContextMenu = contextMenu;
|
||||||
}
|
}
|
||||||
@@ -1011,10 +1022,6 @@ namespace Serein.WorkBench
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 尝试将节点放置在区域中
|
/// 尝试将节点放置在区域中
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -1285,9 +1292,10 @@ namespace Serein.WorkBench
|
|||||||
// 确保起点和终点位置的正确顺序
|
// 确保起点和终点位置的正确顺序
|
||||||
currentLine = new Line
|
currentLine = new Line
|
||||||
{
|
{
|
||||||
Stroke = connectionType == ConnectionType.IsTrue ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#04FC10"))
|
Stroke = connectionType == ConnectionType.IsSucceed ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#04FC10"))
|
||||||
: connectionType == ConnectionType.IsFalse ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#F18905"))
|
: connectionType == ConnectionType.IsFail ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#F18905"))
|
||||||
: new SolidColorBrush((Color)ColorConverter.ConvertFromString("#AB616B")),
|
: connectionType == ConnectionType.IsError ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#AB616B"))
|
||||||
|
: new SolidColorBrush((Color)ColorConverter.ConvertFromString("#4A82E4")),
|
||||||
StrokeDashArray = new DoubleCollection([2]),
|
StrokeDashArray = new DoubleCollection([2]),
|
||||||
StrokeThickness = 2,
|
StrokeThickness = 2,
|
||||||
X1 = Canvas.GetLeft(startConnectBlock) + startConnectBlock.ActualWidth / 2,
|
X1 = Canvas.GetLeft(startConnectBlock) + startConnectBlock.ActualWidth / 2,
|
||||||
@@ -1397,9 +1405,10 @@ namespace Serein.WorkBench
|
|||||||
Line line = new()
|
Line line = new()
|
||||||
{
|
{
|
||||||
IsHitTestVisible = true,
|
IsHitTestVisible = true,
|
||||||
Stroke = currentConnectionType == ConnectionType.IsTrue ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#04FC10"))
|
Stroke = currentConnectionType == ConnectionType.IsSucceed ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#04FC10"))
|
||||||
: currentConnectionType == ConnectionType.IsFalse ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#F18905"))
|
: currentConnectionType == ConnectionType.IsFail ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#F18905"))
|
||||||
: new SolidColorBrush((Color)ColorConverter.ConvertFromString("#AB616B")),
|
: currentConnectionType == ConnectionType.IsError ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#AB616B"))
|
||||||
|
: new SolidColorBrush((Color)ColorConverter.ConvertFromString("#4A82E4")),
|
||||||
StrokeThickness = 2,
|
StrokeThickness = 2,
|
||||||
X1 = Canvas.GetLeft(startConnectBlock) + startConnectBlock.ActualWidth / 2,
|
X1 = Canvas.GetLeft(startConnectBlock) + startConnectBlock.ActualWidth / 2,
|
||||||
Y1 = Canvas.GetTop(startConnectBlock) + startConnectBlock.ActualHeight / 2,
|
Y1 = Canvas.GetTop(startConnectBlock) + startConnectBlock.ActualHeight / 2,
|
||||||
@@ -1419,17 +1428,21 @@ namespace Serein.WorkBench
|
|||||||
FlowChartCanvas.Children.Add(line);
|
FlowChartCanvas.Children.Add(line);
|
||||||
|
|
||||||
|
|
||||||
if (currentConnectionType == ConnectionType.IsTrue)
|
if (currentConnectionType == ConnectionType.IsSucceed)
|
||||||
{
|
{
|
||||||
startConnectBlock.Node.TrueBranch.Add(targetBlock.Node);
|
startConnectBlock.Node.SucceedBranch.Add(targetBlock.Node);
|
||||||
}
|
}
|
||||||
else if (currentConnectionType == ConnectionType.IsFalse)
|
else if (currentConnectionType == ConnectionType.IsFail)
|
||||||
{
|
{
|
||||||
startConnectBlock.Node.FalseBranch.Add(targetBlock.Node);
|
startConnectBlock.Node.FailBranch.Add(targetBlock.Node);
|
||||||
}
|
}
|
||||||
else if (currentConnectionType == ConnectionType.IsEx)
|
else if (currentConnectionType == ConnectionType.IsError)
|
||||||
{
|
{
|
||||||
startConnectBlock.Node.ExBranch.Add(targetBlock.Node);
|
startConnectBlock.Node.ErrorBranch.Add(targetBlock.Node);
|
||||||
|
}
|
||||||
|
else if (currentConnectionType == ConnectionType.Upstream)
|
||||||
|
{
|
||||||
|
startConnectBlock.Node.UpstreamBranch.Add(targetBlock.Node);
|
||||||
}
|
}
|
||||||
|
|
||||||
targetBlock.Node.PreviousNodes.Add(startConnectBlock.Node); // 将当前发起连接的节点,添加到被连接的节点的上一节点队列。(用于回溯)
|
targetBlock.Node.PreviousNodes.Add(startConnectBlock.Node); // 将当前发起连接的节点,添加到被连接的节点的上一节点队列。(用于回溯)
|
||||||
@@ -1597,46 +1610,57 @@ namespace Serein.WorkBench
|
|||||||
{
|
{
|
||||||
var startNode = connection.Start.Node;
|
var startNode = connection.Start.Node;
|
||||||
var endNode = connection.End.Node;
|
var endNode = connection.End.Node;
|
||||||
bool IsStart = false;
|
bool IsStartInThisConnection = false;
|
||||||
// 要删除的节点(targetNode),在连接关系中是否为起点
|
// 要删除的节点(targetNode),在连接关系中是否为起点
|
||||||
// 如果是,则需要从 targetNode 中删除子节点。
|
// 如果是,则需要从 targetNode 中删除子节点。
|
||||||
// 如果不是,则需要从连接关系中的起始节点删除 targetNode 。
|
// 如果不是,则需要从连接关系中的起始节点删除 targetNode 。
|
||||||
if (startNode.Guid.Equals(targetNode.Guid))
|
if (startNode.Guid.Equals(targetNode.Guid))
|
||||||
{
|
{
|
||||||
IsStart = true;
|
IsStartInThisConnection = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connection.Type == ConnectionType.IsTrue)
|
if (connection.Type == ConnectionType.IsSucceed)
|
||||||
{
|
{
|
||||||
if (IsStart)
|
if (IsStartInThisConnection)
|
||||||
{
|
{
|
||||||
targetNode.TrueBranch.Remove(endNode);
|
targetNode.SucceedBranch.Remove(endNode);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
startNode.TrueBranch.Remove(targetNode);
|
startNode.SucceedBranch.Remove(targetNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (connection.Type == ConnectionType.IsFalse)
|
else if (connection.Type == ConnectionType.IsFail)
|
||||||
{
|
{
|
||||||
if (IsStart)
|
if (IsStartInThisConnection)
|
||||||
{
|
{
|
||||||
targetNode.FalseBranch.Remove(endNode);
|
targetNode.FailBranch.Remove(endNode);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
startNode.FalseBranch.Remove(targetNode);
|
startNode.FailBranch.Remove(targetNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (connection.Type == ConnectionType.IsEx)
|
else if (connection.Type == ConnectionType.IsError)
|
||||||
{
|
{
|
||||||
if (IsStart)
|
if (IsStartInThisConnection)
|
||||||
{
|
{
|
||||||
targetNode.ExBranch.Remove(endNode);
|
targetNode.ErrorBranch.Remove(endNode);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
startNode.ExBranch.Remove(targetNode);
|
startNode.ErrorBranch.Remove(targetNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (connection.Type == ConnectionType.Upstream)
|
||||||
|
{
|
||||||
|
if (IsStartInThisConnection)
|
||||||
|
{
|
||||||
|
targetNode.UpstreamBranch.Remove(endNode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
endNode.UpstreamBranch.Remove(targetNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1725,17 +1749,17 @@ namespace Serein.WorkBench
|
|||||||
var StartNode = connectionToRemove.Start.Node;
|
var StartNode = connectionToRemove.Start.Node;
|
||||||
var EndNode = connectionToRemove.End.Node;
|
var EndNode = connectionToRemove.End.Node;
|
||||||
|
|
||||||
if (connectionToRemove.Type == ConnectionType.IsTrue)
|
if (connectionToRemove.Type == ConnectionType.IsSucceed)
|
||||||
{
|
{
|
||||||
StartNode.TrueBranch.Remove(EndNode);
|
StartNode.SucceedBranch.Remove(EndNode);
|
||||||
}
|
}
|
||||||
else if (connectionToRemove.Type == ConnectionType.IsFalse)
|
else if (connectionToRemove.Type == ConnectionType.IsFail)
|
||||||
{
|
{
|
||||||
StartNode.FalseBranch.Remove(EndNode);
|
StartNode.FailBranch.Remove(EndNode);
|
||||||
}
|
}
|
||||||
else if (connectionToRemove.Type == ConnectionType.IsEx)
|
else if (connectionToRemove.Type == ConnectionType.IsError)
|
||||||
{
|
{
|
||||||
StartNode.ExBranch.Remove(EndNode);
|
StartNode.ErrorBranch.Remove(EndNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1823,8 +1847,9 @@ namespace Serein.WorkBench
|
|||||||
{
|
{
|
||||||
var node = item.Node;
|
var node = item.Node;
|
||||||
Point positionRelativeToParent = item.TranslatePoint(new Point(0, 0), FlowChartCanvas);
|
Point positionRelativeToParent = item.TranslatePoint(new Point(0, 0), FlowChartCanvas);
|
||||||
var trueNodes = item.Node.TrueBranch.Select(item => item.Guid); // 真分支
|
var trueNodes = item.Node.SucceedBranch.Select(item => item.Guid); // 真分支
|
||||||
var falseNodes = item.Node.FalseBranch.Select(item => item.Guid);// 加分制
|
var falseNodes = item.Node.FailBranch.Select(item => item.Guid);// 假分支
|
||||||
|
var upstreamNodes = item.Node.UpstreamBranch.Select(item => item.Guid);// 上游分支
|
||||||
|
|
||||||
// 常规节点的参数信息
|
// 常规节点的参数信息
|
||||||
List<Parameterdata> parameterData = [];
|
List<Parameterdata> parameterData = [];
|
||||||
@@ -1883,6 +1908,7 @@ namespace Serein.WorkBench
|
|||||||
},
|
},
|
||||||
trueNodes = trueNodes.ToArray(),
|
trueNodes = trueNodes.ToArray(),
|
||||||
falseNodes = falseNodes.ToArray(),
|
falseNodes = falseNodes.ToArray(),
|
||||||
|
upstreamNodes = upstreamNodes.ToArray(),
|
||||||
parameterData = parameterData.ToArray(),
|
parameterData = parameterData.ToArray(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -144,6 +144,7 @@ namespace Serein.WorkBench
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
||||||
public string[] falseNodes { get; set; }
|
public string[] falseNodes { get; set; }
|
||||||
|
public string[] upstreamNodes { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -154,7 +155,6 @@ namespace Serein.WorkBench
|
|||||||
public class Parameterdata
|
public class Parameterdata
|
||||||
{
|
{
|
||||||
public bool state { get; set; }
|
public bool state { get; set; }
|
||||||
|
|
||||||
public string value { get; set; }
|
public string value { get; set; }
|
||||||
public string expression { get; set; }
|
public string expression { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,16 @@ namespace Serein.WorkBench.Themes
|
|||||||
var members = type.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly);
|
var members = type.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly);
|
||||||
foreach (var member in members)
|
foreach (var member in members)
|
||||||
{
|
{
|
||||||
var memberNode = new TreeViewItem { Header = member.Name };
|
TreeViewItem memberNode;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
memberNode = new TreeViewItem { Header = member.Name };
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (member is PropertyInfo property)
|
if (member is PropertyInfo property)
|
||||||
{
|
{
|
||||||
var propertyType = property.PropertyType;
|
var propertyType = property.PropertyType;
|
||||||
|
|||||||
Reference in New Issue
Block a user