添加了@Dtc(数据类型转换)、@Data(获取全局数据)表达式

This commit is contained in:
fengjiayi
2024-12-09 22:57:06 +08:00
parent 8c54b9a014
commit 0f46b7ef63
27 changed files with 628 additions and 97 deletions

View File

@@ -917,7 +917,30 @@ namespace Serein.Library.Api
#endregion
#region
#region
#region /
/// <summary>
/// 添加或更新全局数据
/// </summary>
/// <param name="keyName">数据名称</param>
/// <param name="data">数据集</param>
/// <returns></returns>
object AddOrUpdateGlobalData(string keyName, object data);
/// <summary>
/// 获取全局数据
/// </summary>
/// <param name="keyName">数据名称</param>
/// <returns></returns>
object GetGlobalData(string keyName);
#endregion
#region
/// <summary>
/// 运行时加载
@@ -933,6 +956,7 @@ namespace Serein.Library.Api
/// <param name="isRecurrence">是否递归加载</param>
void LoadAllNativeLibraryOfRuning(string path, bool isRecurrence = true);
#endregion
#endregion
#region UI视觉

View File

@@ -78,30 +78,34 @@ namespace Serein.Library
args = Array.Empty<object>();
}
object result = null;
try
if (_emitMethodType == EmitMethodType.HasResultTask && _emitDelegate is Func<object, object[], Task<object>> hasResultTask)
{
if (_emitMethodType == EmitMethodType.HasResultTask && _emitDelegate is Func<object, object[], Task<object>> hasResultTask)
{
result = await hasResultTask(instance, args);
}
else if (_emitMethodType == EmitMethodType.Task && _emitDelegate is Func<object, object[], Task> task)
{
await task.Invoke(instance, args);
}
else if (_emitMethodType == EmitMethodType.Func && _emitDelegate is Func<object, object[], object> func)
{
result = func.Invoke(instance, args);
}
else
{
throw new NotImplementedException("创建了非预期委托(应该不会出现)");
}
return result;
result = await hasResultTask(instance, args);
}
catch
else if (_emitMethodType == EmitMethodType.Task && _emitDelegate is Func<object, object[], Task> task)
{
throw;
await task.Invoke(instance, args);
}
else if (_emitMethodType == EmitMethodType.Func && _emitDelegate is Func<object, object[], object> func)
{
result = func.Invoke(instance, args);
}
else
{
throw new NotImplementedException("创建了非预期委托(应该不会出现)");
}
//
return result;
//try
//{
//}
//catch
//{
// throw;
//}
}
}
}

View File

@@ -262,8 +262,9 @@ namespace Serein.Library
catch (Exception ex)
{
newFlowData = null;
await Console.Out.WriteLineAsync($"节点[{this.MethodDetails?.MethodName}]异常:" + ex);
context.Env.WriteLine(InfoType.ERROR,$"节点[{this.Guid}]异常:" + ex);
context.NextOrientation = ConnectionInvokeType.IsError;
context.ExceptionOfRuning = ex;
}
@@ -455,16 +456,31 @@ namespace Serein.Library
}
#endregion
#region Get表达式
if (pd.IsExplicitData // 输入了表达式
&& pd.DataValue.StartsWith("@get", StringComparison.OrdinalIgnoreCase) // Get表达式
)
#region @Get / @DTC Data type conversion / @Data ()
if (pd.IsExplicitData)
{
//var previousNode = context.GetPreviousNode(nodeModel);
//var previousFlowData = context.GetFlowData(previousNode.Guid); // 当前传递的数据
// 执行表达式从上一节点获取对象
inputParameter = SerinExpressionEvaluator.Evaluate(pd.DataValue, inputParameter, out _);
// @Get 表达式 (从上一节点获取对象)
if (pd.DataValue.StartsWith("@get", StringComparison.OrdinalIgnoreCase))
{
inputParameter = SerinExpressionEvaluator.Evaluate(pd.DataValue, inputParameter, out _);
}
// @DTC 表达式 Data type conversion
if (pd.DataValue.StartsWith("@dtc", StringComparison.OrdinalIgnoreCase))
{
inputParameter = SerinExpressionEvaluator.Evaluate(pd.DataValue, inputParameter, out _);
}
// @Data 表达式 (获取全局数据)
if (pd.DataValue.StartsWith("@data", StringComparison.OrdinalIgnoreCase))
{
inputParameter = SerinExpressionEvaluator.Evaluate(pd.DataValue, inputParameter, out _);
}
}
#endregion
#endregion

View File

@@ -6,6 +6,7 @@ using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Text;
namespace Serein.Library
{
@@ -88,21 +89,57 @@ namespace Serein.Library
return value;
}
[NodeAction(NodeType.Action, "文本拼接")]
private string SereinTextJoin(params object[] value)
{
StringBuilder sb = new StringBuilder();
foreach (var item in value)
{
var tmp = item.ToString();
if (tmp == "\\n")
{
sb.Append(Environment.NewLine);
}
else if (tmp == "\\t")
{
sb.Append('\t');
}
else
{
sb.Append(tmp);
}
}
return sb.ToString();
}
/* if (!DynamicObjectHelper.TryResolve(dict, className, out var result))
{
Console.WriteLine("赋值过程中有错误,请检查属性名和类型!");
}
else
{
DynamicObjectHelper.PrintObjectProperties(result);
}
//if (!ObjDynamicCreateHelper.TryResolve(externalData, "RootType", out var result))
//{
// Console.WriteLine("赋值过程中有错误,请检查属性名和类型!");
//}
//ObjDynamicCreateHelper.PrintObjectProperties(result!);
return result;*/
[NodeAction(NodeType.Action, "键值对动态构建对象")]
private object SereinKvDataToObject(Dictionary<string, object> dict,
string classTypeName = "newClass_dynamic",
bool IsPrint = false)
{
if (!DynamicObjectHelper.TryResolve(dict, classTypeName, out var result))
{
Console.WriteLine("赋值过程中有错误,请检查属性名和类型!");
}
else
{
if (IsPrint)
{
Console.WriteLine("创建完成,正在打印结果");
DynamicObjectHelper.PrintObjectProperties(result);
}
}
return result;
}
[NodeAction(NodeType.Action, "设置/更新全局数据")]
private object SereinAddOrUpdateFlowGlobalData(string name,object data)
{
SereinEnv.EnvGlobalData.AddOrUpdate(name, data,(k,o)=> data);
return data;
}
}
}

View File

@@ -201,6 +201,10 @@ namespace Serein.Library.Utils
result = nuint.Parse(valueStr, CultureInfo.InvariantCulture);
}
#endif
else if(type == typeof(DateTime))
{
return DateTime.Parse(valueStr);
}
else
{
throw new ArgumentException("非预期值类型");

View File

@@ -1,5 +1,6 @@
using Serein.Library.Api;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
@@ -11,6 +12,39 @@ namespace Serein.Library.Utils
public static class SereinEnv
{
private static IFlowEnvironment environment;
/// <summary>
/// 记录全局数据
/// </summary>
public static ConcurrentDictionary<string, object> EnvGlobalData { get; } = new ConcurrentDictionary<string, object>();
/// <summary>
/// 清空全局数据
/// </summary>
public static void ClearGlobalData()
{
foreach (var nodeObj in EnvGlobalData.Values)
{
if (nodeObj != null)
{
if (typeof(IDisposable).IsAssignableFrom(nodeObj?.GetType()) && nodeObj is IDisposable disposable)
{
disposable?.Dispose();
}
}
else
{
}
}
EnvGlobalData.Clear();
}
/// <summary>
/// 设置运行流程
/// </summary>
/// <param name="environment"></param>
public static void SetEnv(IFlowEnvironment environment)
{
if (environment != null)
@@ -18,10 +52,22 @@ namespace Serein.Library.Utils
SereinEnv.environment = environment;
}
}
public static void WriteLine(InfoType type, string message, InfoClass @class = InfoClass.Trivial)
/// <summary>
/// 输出内容
/// </summary>
/// <param name="type">类型</param>
/// <param name="message">内容</param>
/// <param name="class">级别</param>
public static void WriteLine(InfoType type, string message, InfoClass @class = InfoClass.General)
{
SereinEnv.environment.WriteLine(type,message,@class);
}
}
}

View File

@@ -3,6 +3,7 @@ using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
@@ -83,6 +84,16 @@ namespace Serein.Library.Utils.SereinExpression
isChange = true;
result = SetMember(targetObJ, operand);
}
else if (operation == "@dtc")
{
isChange = true;
result = DataTypeConversion(targetObJ, operand);
}
else if (operation == "@data")
{
isChange = true;
result = GetGlobleData(targetObJ, operand);
}
else
{
throw new NotSupportedException($"Operation {operation} is not supported.");
@@ -402,11 +413,106 @@ namespace Serein.Library.Utils.SereinExpression
{
return ComputedNumber<decimal>(value, expression);
}
private static T ComputedNumber<T>(object value, string expression) where T : struct, IComparable<T>
{
T result = value.ToConvert<T>();
return SerinArithmeticExpressionEvaluator<T>.Evaluate(expression, result);
}
/// <summary>
/// 数据类型转换
/// </summary>
/// <param name="value"></param>
/// <param name="expression"></param>
/// <returns></returns>
private static object DataTypeConversion(object value, string expression)
{
Type tempType;
int typeStartIndex = expression.IndexOf('<');
int typeEndIndex = expression.IndexOf('>');
string typeStr = expression.Substring(typeStartIndex + 1, typeEndIndex - typeStartIndex - 1)
.Trim().ToLower(); // 手动置顶的类型
string valueStr = expression.Substring(typeEndIndex + 1, expression.Length - typeEndIndex - 1);
switch (typeStr)
{
case "bool":
tempType = typeof(bool);
break;
case "float":
tempType = typeof(float);
break;
case "decimal":
tempType = typeof(decimal);
break;
case "double":
tempType = typeof(double);
break;
case "sbyte":
tempType = typeof(sbyte);
break;
case "byte":
tempType = typeof(byte);
break;
case "short":
tempType = typeof(short);
break;
case "ushort":
tempType = typeof(ushort);
break;
case "int":
tempType = typeof(int);
break;
case "uint":
tempType = typeof(uint);
break;
case "long":
tempType = typeof(long);
break;
case "ulong":
tempType = typeof(ulong);
break;
// 如果需要支持 nint 和 nuint
// case "nint":
// tempType = typeof(nint);
// break;
// case "nuint":
// tempType = typeof(nuint);
// break;
case "string":
tempType = typeof(string);
break;
case "datetime":
tempType = typeof(DateTime);
break;
default:
tempType = Type.GetType(typeStr);
break;
}
if (tempType.IsValueType)
{
return valueStr.ToValueData(tempType);
}
else
{
return null;
}
}
/// <summary>
/// 获取全局数据
/// </summary>
/// <param name="value"></param>
/// <param name="expression"></param>
/// <returns></returns>
private static object GetGlobleData(object value, string expression)
{
var keyName = expression;
SereinEnv.EnvGlobalData.TryGetValue(keyName, out var data);
return data;
}
}
}

View File

@@ -323,8 +323,6 @@ namespace Serein.NodeFlow.Env
/// </summary>
private FlowStarter? flowStarter;
#endregion
#region
@@ -526,6 +524,8 @@ namespace Serein.NodeFlow.Env
}
/// <summary>
/// 加载项目文件
/// </summary>
@@ -535,13 +535,15 @@ namespace Serein.NodeFlow.Env
{
var projectData = flowEnvInfo.Project;
// 加载项目配置文件
var dllPaths = projectData.Librarys.Select(it => it.FileName).ToList();
var dllPaths = projectData.Librarys.Select(it => it.FilePath).ToList();
List<MethodDetails> methodDetailss = [];
// 遍历依赖项中的特性注解,生成方法详情
foreach (var dllPath in dllPaths)
{
var dllFilePath = Path.GetFullPath(Path.Combine(filePath, dllPath));
string cleanedRelativePath = dllPath.TrimStart('.', '\\');
var tmpPath = Path.Combine(filePath, cleanedRelativePath);
var dllFilePath = Path.GetFullPath(tmpPath);
LoadLibrary(dllFilePath); // 加载项目文件时加载对应的程序集
}
@@ -550,39 +552,48 @@ namespace Serein.NodeFlow.Env
// 加载节点
foreach (NodeInfo? nodeInfo in projectData.Nodes)
{
var controlType = FlowFunc.GetNodeControlType(nodeInfo);
NodeControlType controlType = FlowFunc.GetNodeControlType(nodeInfo);
if (controlType == NodeControlType.None)
{
continue;
}
MethodDetails? methodDetails = null;
if (controlType.IsBaseNode())
{
// 加载基础节点
methodDetails = new MethodDetails();
}
else
{
// 加载方法节点
if (string.IsNullOrEmpty(nodeInfo.AssemblyName) && string.IsNullOrEmpty(nodeInfo.MethodName))
{
continue;
}
MethodDetails? methodDetails = null;
FlowLibraryManagement.TryGetMethodDetails(nodeInfo.AssemblyName, nodeInfo.MethodName,out methodDetails); // 加载项目时尝试获取方法信息
var nodeModel = FlowFunc.CreateNode(this, controlType, methodDetails); // 加载项目时创建节点
nodeModel.LoadInfo(nodeInfo); // 创建节点model
if (nodeModel is null)
{
nodeInfo.Guid = string.Empty;
continue;
}
TryAddNode(nodeModel); // 加载项目时将节点加载到环境中
if (nodeInfo.ChildNodeGuids?.Length > 0)
{
regionChildNodes.Add((nodeModel, nodeInfo.ChildNodeGuids));
UIContextOperation?.Invoke(() => OnNodeCreate?.Invoke(new NodeCreateEventArgs(nodeModel, nodeInfo.Position)));
}
else
{
ordinaryNodes.Add((nodeModel, nodeInfo.Position));
}
FlowLibraryManagement.TryGetMethodDetails(nodeInfo.AssemblyName, nodeInfo.MethodName, out methodDetails); // 加载项目时尝试获取方法信息
}
var nodeModel = FlowFunc.CreateNode(this, controlType, methodDetails); // 加载项目时创建节点
nodeModel.LoadInfo(nodeInfo); // 创建节点model
if (nodeModel is null)
{
nodeInfo.Guid = string.Empty;
continue;
}
TryAddNode(nodeModel); // 加载项目时将节点加载到环境中
if (nodeInfo.ChildNodeGuids?.Length > 0)
{
regionChildNodes.Add((nodeModel, nodeInfo.ChildNodeGuids));
UIContextOperation?.Invoke(() => OnNodeCreate?.Invoke(new NodeCreateEventArgs(nodeModel, nodeInfo.Position)));
}
else
{
ordinaryNodes.Add((nodeModel, nodeInfo.Position));
}
}
// 加载区域子项
foreach ((NodeModelBase region, string[] childNodeGuids) item in regionChildNodes)
@@ -1323,7 +1334,6 @@ namespace Serein.NodeFlow.Env
return result;
}
/// <summary>
/// 记录节点更改数据,防止重复更改
/// </summary>
@@ -1466,6 +1476,31 @@ namespace Serein.NodeFlow.Env
#region
/// <summary>
/// 添加或更新全局数据
/// </summary>
/// <param name="keyName">数据名称</param>
/// <param name="data">数据集</param>
/// <returns></returns>
public object AddOrUpdateGlobalData(string keyName, object data)
{
SereinEnv.EnvGlobalData.AddOrUpdate(keyName, data, (k, o) => data);
return data;
}
/// <summary>
/// 获取全局数据
/// </summary>
/// <param name="keyName">数据名称</param>
/// <returns></returns>
public object? GetGlobalData(string keyName)
{
SereinEnv.EnvGlobalData.TryGetValue(keyName, out var data);
return data;
}
/// <summary>
/// 运行时加载
/// </summary>

View File

@@ -455,6 +455,27 @@ namespace Serein.NodeFlow.Env
}
#region
/// <summary>
/// 添加或更新全局数据
/// </summary>
/// <param name="keyName">数据名称</param>
/// <param name="data">数据集</param>
/// <returns></returns>
public object AddOrUpdateGlobalData(string keyName, object data)
{
return currentFlowEnvironment.AddOrUpdateGlobalData(keyName, data);
}
/// <summary>
/// 获取全局数据
/// </summary>
/// <param name="keyName">数据名称</param>
/// <returns></returns>
public object GetGlobalData(string keyName)
{
return currentFlowEnvironment.GetGlobalData(keyName);
}
/// <summary>
/// 运行时加载
@@ -574,6 +595,8 @@ namespace Serein.NodeFlow.Env
return IOC.Run(action);
}
#endregion

View File

@@ -10,7 +10,19 @@ namespace Serein.NodeFlow.Env
/// </summary>
public static class FlowFunc
{
/// <summary>
/// 判断是否为基础节点
/// </summary>
/// <returns></returns>
public static bool IsBaseNode(this NodeControlType nodeControlType)
{
if(nodeControlType == NodeControlType.ExpCondition
|| nodeControlType == NodeControlType.ExpOp)
{
return true;
}
return false;
}
/// <summary>
/// 创建节点

View File

@@ -895,6 +895,31 @@ namespace Serein.NodeFlow.Env
this.WriteLine(InfoType.INFO, "远程环境尚未实现的接口LoadAllNativeLibraryOfRuning");
}
/// <summary>
/// 添加或更新全局数据
/// </summary>
/// <param name="keyName">数据名称</param>
/// <param name="data">数据集</param>
/// <returns></returns>
public object AddOrUpdateGlobalData(string keyName, object data)
{
this.WriteLine(InfoType.INFO, "远程环境尚未实现的接口AddOrUpdateGlobalData");
return null;
}
/// <summary>
/// 获取全局数据
/// </summary>
/// <param name="keyName">数据名称</param>
/// <returns></returns>
public object GetGlobalData(string keyName)
{
this.WriteLine(InfoType.INFO, "远程环境尚未实现的接口GetGlobalData");
return null;
}
#endregion
}
}

View File

@@ -241,13 +241,9 @@ namespace Serein.NodeFlow
_flipFlopCts?.Dispose();
} // 通知所有流程上下文停止运行
TerminateAllGlobalFlipflop(); // 确保所有触发器不再运行
SereinEnv.ClearGlobalData(); // 清空全局数据缓存
NativeDllHelper.FreeLibrarys(); // 卸载所有已加载的 Native Dll
//NativeDllHelper.FreeLibrarys(); // 卸载所有已加载的 Native Dll
env.FlowState = RunState.Completion;
env.FlipFlopState = RunState.Completion;
@@ -395,7 +391,7 @@ namespace Serein.NodeFlow
}
catch (FlipflopException ex)
{
await Console.Out.WriteLineAsync($"触发器[{singleFlipFlopNode.MethodDetails.MethodName}]因非预期异常终止。"+ex.Message);
env.WriteLine(InfoType.ERROR,$"触发器[{singleFlipFlopNode.MethodDetails.MethodName}]因非预期异常终止。"+ex.Message);
if (ex.Type == FlipflopException.CancelClass.CancelFlow)
{
break;
@@ -403,7 +399,8 @@ namespace Serein.NodeFlow
}
catch (Exception ex)
{
await Console.Out.WriteLineAsync(ex.Message);
env.WriteLine(InfoType.ERROR, $"触发器[{singleFlipFlopNode.Guid}]异常。"+ ex.Message);
//await Console.Out.WriteLineAsync(ex.Message);
}
finally
{

View File

@@ -0,0 +1,30 @@
using Serein.Library;
using Serein.Library.Api;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Serein.NodeFlow.Model
{
/// <summary>
/// 全局数据节点
/// </summary>
public class SingleGlobalDataNode : NodeModelBase
{
public SingleGlobalDataNode(IFlowEnvironment environment) : base(environment)
{
}
public override ParameterData[] GetParameterdatas()
{
throw new NotImplementedException();
}
public override void OnCreating()
{
throw new NotImplementedException();
}
}
}

View File

@@ -206,10 +206,8 @@ namespace Serein.NodeFlow.Tool
private (NodeLibraryInfo, List<MethodDetailsInfo>) LoadDllNodeInfo(string dllFilePath)
{
var fileName = Path.GetFileName(dllFilePath); // 获取文件名
if (SereinLibraryDll.Equals(fileName))
{
return LoadAssembly(typeof(IFlowEnvironment).Assembly, () => {
//SereinEnv.PrintInfo(InfoType.WRAN, "基础模块不能卸载");
});

View File

@@ -15,13 +15,14 @@ namespace Serein.Workbench
{
#if DEBUG
if (1 == 1)
if (1 == 0 )
{
string filePath;
filePath = @"F:\临时\project\linux\project.dnf";
filePath = @"F:\临时\project\linux\http\project.dnf";
filePath = @"F:\临时\project\yolo flow\project.dnf";
filePath = @"F:\临时\project\data\project.dnf";
filePath = @"C:\Users\Az\source\repos\CLBanyunqiState\CLBanyunqiState\bin\Release\net8.0\PLCproject.dnf";
string content = System.IO.File.ReadAllText(filePath); // 读取整个文件内容
App.FlowProjectData = JsonConvert.DeserializeObject<SereinProjectData>(content);
App.FileDataPath = System.IO.Path.GetDirectoryName(filePath)!; // filePath;//

View File

@@ -578,7 +578,7 @@ namespace Serein.Workbench
NodeControlType.Action => CreateNodeControl<ActionNodeControl, ActionNodeControlViewModel>(nodeModelBase), //typeof(ActionNodeControl),
NodeControlType.Flipflop => CreateNodeControl<FlipflopNodeControl, FlipflopNodeControlViewModel>(nodeModelBase),
NodeControlType.ExpCondition => CreateNodeControl<ConditionNodeControl, ConditionNodeControlViewModel>(nodeModelBase),
NodeControlType.ExpOp => CreateNodeControl<ExpOpNodeControl, ExpOpNodeViewModel>(nodeModelBase),
NodeControlType.ExpOp => CreateNodeControl<ExpOpNodeControl, ExpOpNodeControlViewModel>(nodeModelBase),
NodeControlType.ConditionRegion => CreateNodeControl<ConditionRegionControl, ConditionRegionNodeControlViewModel>(nodeModelBase),
_ => null,
};
@@ -2504,7 +2504,7 @@ namespace Serein.Workbench
NodeLibraryInfo? library = projectData.Librarys[index];
try
{
string targetPath = System.IO.Path.Combine(librarySavePath, library.FileName); // 目标文件夹
string targetPath = System.IO.Path.Combine(librarySavePath, library.FilePath); // 目标文件夹
#if WINDOWS
string sourceFile = library.FilePath; // 源文件夹
#else

View File

@@ -15,8 +15,10 @@
<!--<BooleanToVisibilityConverter x:Key="BoolToVisConverter" />-->
<converters:InvertableBooleanToVisibilityConverter x:Key="InvertedBoolConverter"/>
<!--<ResourceDictionary Source="/Serein.Workbench;Node/View/NodeExecuteJunctionControl.xaml" x:Key="NodeExecuteJunctionControl"/>-->
</UserControl.Resources>
<Border BorderBrush="#8DE9FD" BorderThickness="4">
<Grid>
<Grid.ToolTip>
@@ -24,7 +26,10 @@
</Grid.ToolTip>
<!--<TextBlock Text="{Binding NodelModel.DebugSetting.IsInterrupt}}"></TextBlock>-->
<Border x:Name="InterruptBorder" DataContext="{Binding}">
<!--DataContext="{Binding}-->
<Border x:Name="InterruptBorder" Tag="{Binding NodeModel.DebugSetting.IsInterrupt}">
<Border.Style>
<Style TargetType="Border">
<!--默认无边框-->
@@ -32,9 +37,9 @@
<Setter Property="BorderThickness" Value="0" />
<Style.Triggers>
<!--NodeModel.DebugSetting.IsInterrupt-->
<!--<DataTrigger Binding="{Binding DataContext.NodeModel.DebugSetting.IsInterrup, RelativeSource={RelativeSource AncestorType=UserControl}}" Value="True">-->
<DataTrigger Binding="{Binding IsInterrupt,Mode=OneTime}" Value="True">
<!--<DataTrigger Binding="{Binding NodeModel.DebugSetting.IsInterrup}" Value="True">-->
<!--<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:ActionNodeControl}}, Path=DataContext.DebugSetting.IsInterrupt}" Value="True">-->
<!--<DataTrigger Binding="{Binding DebugSetting.IsInterrupt, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Value="True">-->
<DataTrigger Binding="{Binding Path=Tag,RelativeSource={RelativeSource Mode=Self}}" Value="True">
<Setter Property="BorderBrush" Value="Red" />
<Setter Property="BorderThickness" Value="2" />
<Setter Property="Background" Value="#80000000" />
@@ -42,8 +47,12 @@
</Style.Triggers>
</Style>
</Border.Style>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>

View File

@@ -16,7 +16,11 @@ namespace Serein.Workbench.Node.View
{
DataContext = viewModel;
InitializeComponent();
if(ExecuteJunctionControl.MyNode != null)
{
ExecuteJunctionControl.MyNode.Guid = viewModel.NodeModel.Guid;
}
}
/// <summary>

View File

@@ -21,6 +21,7 @@ namespace Serein.Workbench.Node.View
DataContext = viewModel;
InitializeComponent();
}
/// <summary>
/// 入参控制点(可能有,可能没)
/// </summary>

View File

@@ -26,8 +26,6 @@ namespace Serein.Workbench.Node.View
/// <summary>
/// 添加条件控件
/// </summary>

View File

@@ -11,11 +11,11 @@ namespace Serein.Workbench.Node.View
public ExpOpNodeControl() : base()
{
// 窗体初始化需要
ViewModel = new ExpOpNodeViewModel(new SingleExpOpNode(null));
ViewModel = new ExpOpNodeControlViewModel(new SingleExpOpNode(null));
DataContext = ViewModel;
InitializeComponent();
}
public ExpOpNodeControl(ExpOpNodeViewModel viewModel) :base(viewModel)
public ExpOpNodeControl(ExpOpNodeControlViewModel viewModel) :base(viewModel)
{
DataContext = viewModel;
InitializeComponent();

View File

@@ -55,6 +55,11 @@
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<!--<PackageReference Include="MySqlConnector" Version="2.4.0" />
<PackageReference Include="SqlSugarCore" Version="5.1.4.170" />
<PackageReference Include="SqlSugarCoreNoDrive" Version="5.1.4.171" />-->
<!--<PackageReference Include="LivetCask2" Version="4.0.2" />-->
<!--<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.39" />-->
</ItemGroup>

View File

@@ -46,6 +46,7 @@
Visibility="{Binding IsParams, Mode=OneWay,
Converter={StaticResource InvertedBoolConverter},ConverterParameter=Normal}"
/>
<ContentControl Content="{Binding}" Grid.Column="4" VerticalAlignment="Center">
<ContentControl.Style>
<Style TargetType="ContentControl">

View File

@@ -0,0 +1,75 @@
<local:NodeControlBase x:Class="Serein.Workbench.Node.View.GlobalDataControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Serein.Workbench.Node.View"
xmlns:vm="clr-namespace:Serein.Workbench.Node.ViewModel"
d:DataContext="{d:DesignInstance vm:GlobalDataNodeControlViewModel}"
mc:Ignorable="d"
MaxWidth="300">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis" />
</UserControl.Resources>
<Grid>
<Grid.ToolTip>
<ToolTip Background="LightYellow" Foreground="Black" Content="{Binding NodeModel.MethodDetails.MethodAnotherName, UpdateSourceTrigger=PropertyChanged}" />
</Grid.ToolTip>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="#E7EFF5" >
<!--<Grid Grid.Row="0" >-->
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<local:ExecuteJunctionControl Grid.Column="0" MyNode="{Binding NodeModel}" x:Name="ExecuteJunctionControl" HorizontalAlignment="Left" Grid.RowSpan="2"/>
<Border Grid.Column="1" BorderThickness="1" HorizontalAlignment="Stretch">
<TextBlock Text="全局数据" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<local:NextStepJunctionControl Grid.Column="2" MyNode="{Binding NodeModel}" x:Name="NextStepJunctionControl" HorizontalAlignment="Right" Grid.RowSpan="2"/>
</Grid>
<Grid Grid.Row="1" Background="#FEFAF4" HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="名称" Margin="2" HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
<TextBox Grid.Row="0" Grid.Column="1" MinWidth="50" Margin="2" Text="{Binding NodeModel.CustomData, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Stretch" VerticalAlignment="Center">
</TextBox>
<StackPanel Grid.Row="1" Grid.ColumnSpan="2" Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock Text="设置数据源" Margin="2" HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
<local:ResultJunctionControl Grid.Column="2" MyNode="{Binding NodelModel}" x:Name="ResultJunctionControl" HorizontalAlignment="Right"/>
</StackPanel>
</Grid>
<!--<themes:MethodDetailsControl Grid.Row="1" MethodDetails="{Binding MethodDetails}" />
<Border Grid.Row="2" Background="#EAFFD0" BorderBrush="#EAFFD0" BorderThickness="1">
<TextBlock Text="{Binding MethodDetails.MethodTips, Converter={StaticResource TypeToStringConverter}, StringFormat=return:{0}, UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>-->
</Grid>
</local:NodeControlBase>

View File

@@ -0,0 +1,62 @@
using Serein.NodeFlow.Model;
using Serein.Workbench.Node.ViewModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Serein.Workbench.Node.View
{
/// <summary>
/// UserControl1.xaml 的交互逻辑
/// </summary>
public partial class GlobalDataControl : NodeControlBase, INodeJunction
{
public GlobalDataControl() : base()
{
// 窗体初始化需要
ViewModel = new GlobalDataNodeControlViewModel(new SingleGlobalDataNode(null));
DataContext = ViewModel;
InitializeComponent();
}
public GlobalDataControl(ConditionNodeControlViewModel viewModel) : base(viewModel)
{
DataContext = viewModel;
InitializeComponent();
}
/// <summary>
/// 入参控制点(可能有,可能没)
/// </summary>
JunctionControlBase INodeJunction.ExecuteJunction => this.ExecuteJunctionControl;
/// <summary>
/// 下一个调用方法控制点(可能有,可能没)
/// </summary>
JunctionControlBase INodeJunction.NextStepJunction => this.NextStepJunctionControl;
/// <summary>
/// 返回值控制点(可能有,可能没)
/// </summary>
JunctionControlBase INodeJunction.ReturnDataJunction => this.ResultJunctionControl;
/// <summary>
/// 方法入参控制点(可能有,可能没)
/// </summary>
JunctionControlBase[] INodeJunction.ArgDataJunction => throw new NotImplementedException();
}
}

View File

@@ -3,7 +3,7 @@ using Serein.Workbench.Node.View;
namespace Serein.Workbench.Node.ViewModel
{
public class ExpOpNodeViewModel: NodeControlViewModelBase
public class ExpOpNodeControlViewModel: NodeControlViewModelBase
{
public new SingleExpOpNode NodeModel { get; }
@@ -18,7 +18,7 @@ namespace Serein.Workbench.Node.ViewModel
//}
public ExpOpNodeViewModel(SingleExpOpNode nodeModel) : base(nodeModel)
public ExpOpNodeControlViewModel(SingleExpOpNode nodeModel) : base(nodeModel)
{
this.NodeModel = nodeModel;
}

View File

@@ -0,0 +1,18 @@
using Serein.NodeFlow.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Serein.Workbench.Node.ViewModel
{
public class GlobalDataNodeControlViewModel : NodeControlViewModelBase
{
public new SingleGlobalDataNode NodelModel { get; }
public GlobalDataNodeControlViewModel(SingleGlobalDataNode node) : base(node)
{
this.NodelModel = node;
}
}
}