mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-05-01 03:53:22 +08:00
脚本节点能够自定义变量名
This commit is contained in:
@@ -110,7 +110,9 @@ namespace Serein.Library
|
|||||||
SourceNodeGuid = it.ArgDataSourceNodeGuid,
|
SourceNodeGuid = it.ArgDataSourceNodeGuid,
|
||||||
SourceType = it.ArgDataSourceType.ToString(),
|
SourceType = it.ArgDataSourceType.ToString(),
|
||||||
State = it.IsExplicitData,
|
State = it.IsExplicitData,
|
||||||
|
ArgName = it.Name,
|
||||||
Value = it.DataValue,
|
Value = it.DataValue,
|
||||||
|
|
||||||
})
|
})
|
||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ namespace Serein.Library
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 方法入参参数名称
|
/// 方法入参参数名称
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PropertyInfo]
|
[PropertyInfo(IsNotification = true)]
|
||||||
private string _name ;
|
private string _name ;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -277,11 +277,13 @@ namespace Serein.Library
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ParameterData
|
public class ParameterData
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 参数类型,true时使用自定义的入参,false时由运行环境自动传参
|
/// 参数类型,true时使用自定义的入参,false时由运行环境自动传参
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool State { get; set; }
|
public bool State { get; set; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 参数来源节点
|
/// 参数来源节点
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -292,16 +294,17 @@ namespace Serein.Library
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string SourceType { get; set; }
|
public string SourceType { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 参数名称
|
||||||
|
/// </summary>
|
||||||
|
public string ArgName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 自定义入参
|
/// 自定义入参
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Value { get; set; }
|
public string Value { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 表达式相关节点的表达式内容
|
|
||||||
/// </summary>
|
|
||||||
// public string Expression { get; set; }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ namespace Serein.NodeFlow.Model
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override void OnCreating()
|
public override void OnCreating()
|
||||||
{
|
{
|
||||||
MethodInfo? method = this.GetType().GetMethod(nameof(GetFlowApi));
|
MethodInfo? method = this.GetType().GetMethod(nameof(GetFlowApi));
|
||||||
@@ -115,6 +116,14 @@ namespace Serein.NodeFlow.Model
|
|||||||
public override void LoadCustomData(NodeInfo nodeInfo)
|
public override void LoadCustomData(NodeInfo nodeInfo)
|
||||||
{
|
{
|
||||||
this.Script = nodeInfo.CustomData?.Script ?? "";
|
this.Script = nodeInfo.CustomData?.Script ?? "";
|
||||||
|
|
||||||
|
// 更新变量名
|
||||||
|
for (int i = 0; i < Math.Min(this.MethodDetails.ParameterDetailss.Length, nodeInfo.ParameterData.Length); i++)
|
||||||
|
{
|
||||||
|
this.MethodDetails.ParameterDetailss[i].Name = nodeInfo.ParameterData[i].ArgName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -124,12 +133,30 @@ namespace Serein.NodeFlow.Model
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
HashSet<string> varNames = new HashSet<string>();
|
||||||
|
foreach (var pd in MethodDetails.ParameterDetailss)
|
||||||
|
{
|
||||||
|
if (varNames.Contains(pd.Name))
|
||||||
|
{
|
||||||
|
throw new Exception($"脚本节点重复的变量名称:{pd.Name} - {Guid}");
|
||||||
|
}
|
||||||
|
varNames.Add(pd.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
//StringBuilder sb = new StringBuilder();
|
||||||
|
//foreach (var pd in MethodDetails.ParameterDetailss)
|
||||||
|
//{
|
||||||
|
// sb.AppendLine($"let {pd.Name};"); // 提前声明这些变量
|
||||||
|
//}
|
||||||
|
//sb.Append(Script);
|
||||||
|
//var p = new SereinScriptParser(sb.ToString());
|
||||||
var p = new SereinScriptParser(Script);
|
var p = new SereinScriptParser(Script);
|
||||||
mainNode = p.Parse();
|
mainNode = p.Parse(); // 开始解析
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
SereinEnv.WriteLine(InfoType.ERROR, ex.ToString());
|
SereinEnv.WriteLine(InfoType.ERROR, ex.ToString());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,21 +168,23 @@ namespace Serein.NodeFlow.Model
|
|||||||
public override async Task<object?> ExecutingAsync(IDynamicContext context)
|
public override async Task<object?> ExecutingAsync(IDynamicContext context)
|
||||||
{
|
{
|
||||||
var @params = await GetParametersAsync(context);
|
var @params = await GetParametersAsync(context);
|
||||||
//dynamic obj = ((object[])@params[0])[0];
|
|
||||||
//try
|
|
||||||
//{
|
|
||||||
// SereinEnv.WriteLine(InfoType.INFO, "Dynamic Object Value :" + obj.VarInfo);
|
|
||||||
//}
|
|
||||||
//catch (Exception ex)
|
|
||||||
//{
|
|
||||||
// SereinEnv.WriteLine(ex);
|
|
||||||
//}
|
|
||||||
//ScriptFlowApi.Context = context; // 并发破坏了数据状态
|
|
||||||
context.AddOrUpdate($"{context.Guid}_{this.Guid}_Params", @params[0]); // 后面再改
|
|
||||||
|
|
||||||
mainNode ??= new SereinScriptParser(Script).Parse();
|
//context.AddOrUpdate($"{context.Guid}_{this.Guid}_Params", @params[0]); // 后面再改
|
||||||
|
ReloadScript();// 每次都重新解析
|
||||||
|
|
||||||
IScriptInvokeContext scriptContext = new ScriptInvokeContext(context);
|
IScriptInvokeContext scriptContext = new ScriptInvokeContext(context);
|
||||||
|
|
||||||
|
if (@params[0] is object[] agrDatas)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < agrDatas.Length; i++)
|
||||||
|
{
|
||||||
|
var argName = MethodDetails.ParameterDetailss[i].Name;
|
||||||
|
var argData = agrDatas[i];
|
||||||
|
scriptContext.SetVarValue(argName, argData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var result = await ScriptInterpreter.InterpretAsync(scriptContext, mainNode); // 从入口节点执行
|
var result = await ScriptInterpreter.InterpretAsync(scriptContext, mainNode); // 从入口节点执行
|
||||||
//SereinEnv.WriteLine(InfoType.INFO, "FlowContext Guid : " + context.Guid);
|
//SereinEnv.WriteLine(InfoType.INFO, "FlowContext Guid : " + context.Guid);
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -8,12 +8,19 @@ namespace Serein.Script.Node
|
|||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 变量节点
|
/// 赋值节点
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AssignmentNode : ASTNode
|
public class AssignmentNode : ASTNode
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 变量名称
|
||||||
|
/// </summary>
|
||||||
public string Variable { get; }
|
public string Variable { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// 对应的节点
|
||||||
|
/// </summary>
|
||||||
public ASTNode Value { get; }
|
public ASTNode Value { get; }
|
||||||
|
|
||||||
public AssignmentNode(string variable, ASTNode value) => (Variable, Value) = (variable, value);
|
public AssignmentNode(string variable, ASTNode value) => (Variable, Value) = (variable, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -212,6 +212,8 @@ namespace Serein.Script
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private async Task<object?> ExecutionProgramNodeAsync(IScriptInvokeContext context, ProgramNode programNode)
|
private async Task<object?> ExecutionProgramNodeAsync(IScriptInvokeContext context, ProgramNode programNode)
|
||||||
{
|
{
|
||||||
|
// 加载变量
|
||||||
|
|
||||||
// 遍历 ProgramNode 中的所有语句并执行它们
|
// 遍历 ProgramNode 中的所有语句并执行它们
|
||||||
foreach (var statement in programNode.Statements)
|
foreach (var statement in programNode.Statements)
|
||||||
{
|
{
|
||||||
@@ -366,8 +368,6 @@ namespace Serein.Script
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public async Task<object?> InterpretAsync(IScriptInvokeContext context, ASTNode node)
|
public async Task<object?> InterpretAsync(IScriptInvokeContext context, ASTNode node)
|
||||||
{
|
{
|
||||||
if(node == null)
|
if(node == null)
|
||||||
|
|||||||
@@ -3,12 +3,17 @@
|
|||||||
xmlns:local="clr-namespace:Serein.Workbench.Themes"
|
xmlns:local="clr-namespace:Serein.Workbench.Themes"
|
||||||
xmlns:view="clr-namespace:Serein.Workbench.Node.View"
|
xmlns:view="clr-namespace:Serein.Workbench.Node.View"
|
||||||
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:serein="clr-namespace:Serein.Library;assembly=Serein.Library"
|
||||||
xmlns:converters="clr-namespace:Serein.Workbench.Tool.Converters">
|
xmlns:converters="clr-namespace:Serein.Workbench.Tool.Converters">
|
||||||
|
|
||||||
|
|
||||||
<ResourceDictionary.MergedDictionaries>
|
<ResourceDictionary.MergedDictionaries>
|
||||||
</ResourceDictionary.MergedDictionaries>
|
</ResourceDictionary.MergedDictionaries>
|
||||||
|
|
||||||
|
|
||||||
<converters:InvertableBooleanToVisibilityConverter x:Key="InvertedBoolConverter"/>
|
<converters:InvertableBooleanToVisibilityConverter x:Key="InvertedBoolConverter"/>
|
||||||
|
<converters:EnumToBooleanConverter x:Key="EnumToBooleanConverter"/>
|
||||||
|
|
||||||
<Style TargetType="{x:Type local:MethodDetailsControl}">
|
<Style TargetType="{x:Type local:MethodDetailsControl}">
|
||||||
<Setter Property="Template">
|
<Setter Property="Template">
|
||||||
@@ -18,8 +23,8 @@
|
|||||||
<!--根据方法入参数量生成相应的控件-->
|
<!--根据方法入参数量生成相应的控件-->
|
||||||
<ItemsControl ItemsSource="{Binding MethodDetails.ParameterDetailss, RelativeSource={RelativeSource TemplatedParent}}" Background="#E3FDFD" >
|
<ItemsControl ItemsSource="{Binding MethodDetails.ParameterDetailss, RelativeSource={RelativeSource TemplatedParent}}" Background="#E3FDFD" >
|
||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate DataType="serein:ParameterData">
|
||||||
<Grid >
|
<Grid DataContext="{Binding}">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="auto"/>
|
<ColumnDefinition Width="auto"/>
|
||||||
<ColumnDefinition Width="auto"/>
|
<ColumnDefinition Width="auto"/>
|
||||||
@@ -31,11 +36,70 @@
|
|||||||
<!--连接控制器-->
|
<!--连接控制器-->
|
||||||
<view:ArgJunctionControl x:Name="ArgJunctionControl" Grid.Column="0" ArgIndex="{Binding Index}" MyNode="{Binding NodeModel}" />
|
<view:ArgJunctionControl x:Name="ArgJunctionControl" Grid.Column="0" ArgIndex="{Binding Index}" MyNode="{Binding NodeModel}" />
|
||||||
<!--参数索引提示-->
|
<!--参数索引提示-->
|
||||||
<TextBlock Grid.Column="1" Text="{Binding Index,StringFormat=agr{0}}" Margin="2,0,2,0" VerticalAlignment="Center"/>
|
<!--<TextBlock Grid.Column="1" Text="{Binding Index,StringFormat=agr{0}}" Margin="2,0,2,0" VerticalAlignment="Center"/>-->
|
||||||
|
|
||||||
<!--是否设置为显式参数-->
|
<!--是否设置为显式参数-->
|
||||||
<CheckBox Grid.Column="2" IsChecked="{Binding IsExplicitData, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="2,0,2,0" VerticalContentAlignment="Center"/>
|
<CheckBox Grid.Column="2" IsChecked="{Binding IsExplicitData, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="2,0,2,0" VerticalContentAlignment="Center"/>
|
||||||
|
|
||||||
|
|
||||||
<!--入参参数名称-->
|
<!--入参参数名称-->
|
||||||
<TextBlock Grid.Column="3" MinWidth="50" Text="{Binding Name}" Margin="2,0,2,0" HorizontalAlignment="Left" VerticalAlignment="Center"/>
|
<ContentControl Content="{Binding}" Grid.Column="3" Margin="2,0,2,0" HorizontalAlignment="Left" VerticalAlignment="Center">
|
||||||
|
<ContentControl.Resources>
|
||||||
|
<local:DataContextProxy x:Key="Proxy"
|
||||||
|
DataContext="{Binding}" />
|
||||||
|
</ContentControl.Resources>
|
||||||
|
<ContentControl.Style>
|
||||||
|
<Style TargetType="ContentControl">
|
||||||
|
<Style.Triggers>
|
||||||
|
|
||||||
|
<!--脚本节点输入变量名称-->
|
||||||
|
<MultiDataTrigger>
|
||||||
|
<MultiDataTrigger.Conditions>
|
||||||
|
<Condition Binding="{Binding NodeModel.ControlType}" Value="{x:Static serein:NodeControlType.Script}"/>
|
||||||
|
</MultiDataTrigger.Conditions>
|
||||||
|
<Setter Property="ContentTemplate">
|
||||||
|
<Setter.Value>
|
||||||
|
<DataTemplate>
|
||||||
|
<TextBox MinWidth="50" Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"/>
|
||||||
|
</DataTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</MultiDataTrigger>
|
||||||
|
|
||||||
|
|
||||||
|
<!--显示Action节点方法入参名称-->
|
||||||
|
<MultiDataTrigger>
|
||||||
|
<MultiDataTrigger.Conditions>
|
||||||
|
<Condition Binding="{Binding NodeModel.ControlType}" Value="{x:Static serein:NodeControlType.Action}"/>
|
||||||
|
</MultiDataTrigger.Conditions>
|
||||||
|
<Setter Property="ContentTemplate">
|
||||||
|
<Setter.Value>
|
||||||
|
<DataTemplate>
|
||||||
|
<TextBlock Grid.Column="0" MinWidth="50" Text="{Binding Name}"/>
|
||||||
|
</DataTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</MultiDataTrigger>
|
||||||
|
|
||||||
|
<!--显示Flip方法入参名称-->
|
||||||
|
<MultiDataTrigger>
|
||||||
|
<MultiDataTrigger.Conditions>
|
||||||
|
<Condition Binding="{Binding NodeModel.ControlType}" Value="{x:Static serein:NodeControlType.Flipflop}"/>
|
||||||
|
</MultiDataTrigger.Conditions>
|
||||||
|
<Setter Property="ContentTemplate">
|
||||||
|
<Setter.Value>
|
||||||
|
<DataTemplate>
|
||||||
|
<TextBlock Grid.Column="0" MinWidth="50" Text="{Binding Name}"/>
|
||||||
|
</DataTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</MultiDataTrigger>
|
||||||
|
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</ContentControl.Style>
|
||||||
|
</ContentControl>
|
||||||
|
|
||||||
<!--增加可选参数(如果有)-->
|
<!--增加可选参数(如果有)-->
|
||||||
<view:ParamsArgControl x:Name="ParamsArgControl"
|
<view:ParamsArgControl x:Name="ParamsArgControl"
|
||||||
ArgIndex="{Binding Index}"
|
ArgIndex="{Binding Index}"
|
||||||
@@ -44,7 +108,7 @@
|
|||||||
Grid.Column="5" Margin="2,0,2,0" HorizontalAlignment="Right" VerticalAlignment="Center"
|
Grid.Column="5" Margin="2,0,2,0" HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
Visibility="{Binding IsParams, Mode=OneWay,
|
Visibility="{Binding IsParams, Mode=OneWay,
|
||||||
Converter={StaticResource InvertedBoolConverter},ConverterParameter=Normal}"
|
Converter={StaticResource InvertedBoolConverter},ConverterParameter=Normal}"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ContentControl Content="{Binding}" Grid.Column="4" VerticalAlignment="Center">
|
<ContentControl Content="{Binding}" Grid.Column="4" VerticalAlignment="Center">
|
||||||
<ContentControl.Style>
|
<ContentControl.Style>
|
||||||
|
|||||||
@@ -39,6 +39,29 @@ namespace Serein.Workbench.Themes
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class DataContextProxy : Freezable
|
||||||
|
{
|
||||||
|
public DataContextProxy()
|
||||||
|
{
|
||||||
|
BindingOperations.SetBinding(this, DataContextProperty, new Binding());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParameterDetails DataContext
|
||||||
|
{
|
||||||
|
get { return (ParameterDetails)GetValue(DataContextProperty); }
|
||||||
|
set { SetValue(DataContextProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static readonly DependencyProperty DataContextProperty = FrameworkElement
|
||||||
|
.DataContextProperty.AddOwner(typeof(DataContextProxy));
|
||||||
|
|
||||||
|
protected override Freezable CreateInstanceCore()
|
||||||
|
{
|
||||||
|
return new DataContextProxy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 方法参数控件
|
/// 方法参数控件
|
||||||
@@ -78,13 +101,17 @@ namespace Serein.Workbench.Themes
|
|||||||
CommandAddParams = new RelayCommand(ExecuteAddParams);
|
CommandAddParams = new RelayCommand(ExecuteAddParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void ExecuteAddParams(object parameter)
|
private void ExecuteAddParams(object parameter)
|
||||||
{
|
{
|
||||||
// 方法逻辑
|
// 方法逻辑
|
||||||
this.MethodDetails.AddParamsArg();
|
this.MethodDetails.AddParamsArg();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
27
Workbench/Tool/Converters/EnumToBooleanConverter.cs
Normal file
27
Workbench/Tool/Converters/EnumToBooleanConverter.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Data;
|
||||||
|
|
||||||
|
namespace Serein.Workbench.Tool.Converters
|
||||||
|
{
|
||||||
|
public class EnumToBooleanConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if (value == null || parameter == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return value.ToString().Equals(parameter.ToString(), StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user