using XFEWorkflow.Abstractions;
using XFEWorkflow.Infrastructure.Execution;
using XFEWorkflow.Services;
namespace XFEWorkflow.Controls;
public sealed class WorkflowLibrary : UserControl
{
private readonly TextBox search = new() { PlaceholderText = "搜索所有工作流", Margin = new(0, 0, 0, 8) };
private readonly StackPanel items = new() { Spacing = 6 };
private IReadOnlyList<WorkflowDefinition> workflows = [];
public event Action<WorkflowDefinition, bool>? Invoked;
public WorkflowLibrary()
{
var root = new Grid(); root.RowDefinitions.Add(new() { Height = GridLength.Auto }); root.RowDefinitions.Add(new());
root.Children.Add(search); var scroll = new ScrollViewer { Content = items, MaxHeight = 280, HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled }; Grid.SetRow(scroll, 1); root.Children.Add(scroll); Content = root;
search.TextChanged += (_, _) => Render();
}
public void SetWorkflows(IEnumerable<WorkflowDefinition> source) { workflows = source.ToArray(); Render(); }
private void Render()
{
var expanded = items.Children.OfType<Expander>().Where(x => x.IsExpanded).Select(x => x.Tag as string).ToHashSet();
items.Children.Clear();
foreach (var workflow in workflows.Where(x => x.Name.Contains(search.Text.Trim(), StringComparison.OrdinalIgnoreCase)))
{
var content = new StackPanel { Spacing = 8 };
var triggers = AppServices.Current.Scheduler.StatusFor(workflow);
content.Children.Add(new TextBlock { Text = workflow.Kind == WorkflowKind.CSharp ? "C# 代码工作流" : "图形化工作流", Opacity = .7, FontSize = 12 });
if (triggers.Count == 0) content.Children.Add(new TextBlock { Text = "仅手动运行 · 添加触发器即可自动执行", TextWrapping = TextWrapping.Wrap, FontSize = 12 });
foreach (var trigger in triggers) content.Children.Add(new TextBlock { Text = trigger.Label + (!trigger.Enabled ? " · 已停用" : trigger.Error is { } error ? " · " + error : AppServices.Current.Scheduler.IsSuspended ? " · 调度已暂停" : trigger.NextRun is { } next ? $" · 下次 {next.ToLocalTime():MM-dd HH:mm:ss}" : " · 监听中"), TextWrapping = TextWrapping.Wrap, FontSize = 12 });
var actions = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 8 };
var open = new Button { Content = "打开工作流" }; open.Click += (_, _) => Invoked?.Invoke(workflow, false);
var configure = new Button { Content = "查看触发节点" }; configure.Click += (_, _) => Invoked?.Invoke(workflow, true);
actions.Children.Add(open); actions.Children.Add(configure); content.Children.Add(actions);
var header = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 10 };
header.Children.Add(new FontIcon { Glyph = "\uEF90", FontSize = 16 });
header.Children.Add(new TextBlock { Text = workflow.Name, TextTrimming = TextTrimming.CharacterEllipsis });
header.Children.Add(new TextBlock { Text = $"{triggers.Count(x => x.Enabled)} 个触发器", Opacity = .6, FontSize = 12 });
items.Children.Add(new Expander { Header = header, Tag = workflow.Id, Content = content, IsExpanded = expanded.Contains(workflow.Id), HorizontalAlignment = HorizontalAlignment.Stretch, HorizontalContentAlignment = HorizontalAlignment.Stretch });
}
if (items.Children.Count == 0) items.Children.Add(new TextBlock { Text = "没有匹配的工作流", Margin = new(12) });
}
}
using XFEWorkflow.Abstractions;
using XFEWorkflow.Infrastructure.Execution;
using XFEWorkflow.Services;
namespace XFEWorkflow.Controls;
public sealed class WorkflowLibrary : UserControl
{
private readonly TextBox search = new() { PlaceholderText = "搜索所有工作流", Margin = new(0, 0, 0, 8) };
private readonly StackPanel items = new() { Spacing = 6 };
private IReadOnlyList<WorkflowDefinition> workflows = [];
public event Action<WorkflowDefinition, bool>? Invoked;
public WorkflowLibrary()
{
var root = new Grid(); root.RowDefinitions.Add(new() { Height = GridLength.Auto }); root.RowDefinitions.Add(new());
root.Children.Add(search); var scroll = new ScrollViewer { Content = items, MaxHeight = 280, HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled }; Grid.SetRow(scroll, 1); root.Children.Add(scroll); Content = root;
search.TextChanged += (_, _) => Render();
}
public void SetWorkflows(IEnumerable<WorkflowDefinition> source) { workflows = source.ToArray(); Render(); }
private void Render()
{
var expanded = items.Children.OfType<Expander>().Where(x => x.IsExpanded).Select(x => x.Tag as string).ToHashSet();
items.Children.Clear();
foreach (var workflow in workflows.Where(x => x.Name.Contains(search.Text.Trim(), StringComparison.OrdinalIgnoreCase)))
{
var content = new StackPanel { Spacing = 8 };
var triggers = AppServices.Current.Scheduler.StatusFor(workflow);
content.Children.Add(new TextBlock { Text = workflow.Kind == WorkflowKind.CSharp ? "C# 代码工作流" : "图形化工作流", Opacity = .7, FontSize = 12 });
if (triggers.Count == 0) content.Children.Add(new TextBlock { Text = "仅手动运行 · 添加触发器即可自动执行", TextWrapping = TextWrapping.Wrap, FontSize = 12 });
foreach (var trigger in triggers) content.Children.Add(new TextBlock { Text = trigger.Label + (!trigger.Enabled ? " · 已停用" : trigger.Error is { } error ? " · " + error : AppServices.Current.Scheduler.IsSuspended ? " · 调度已暂停" : trigger.NextRun is { } next ? $" · 下次 {next.ToLocalTime():MM-dd HH:mm:ss}" : " · 监听中"), TextWrapping = TextWrapping.Wrap, FontSize = 12 });
var actions = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 8 };
var open = new Button { Content = "打开工作流" }; open.Click += (_, _) => Invoked?.Invoke(workflow, false);
var configure = new Button { Content = "查看触发节点" }; configure.Click += (_, _) => Invoked?.Invoke(workflow, true);
actions.Children.Add(open); actions.Children.Add(configure); content.Children.Add(actions);
var header = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 10 };
header.Children.Add(new FontIcon { Glyph = "\uEF90", FontSize = 16 });
header.Children.Add(new TextBlock { Text = workflow.Name, TextTrimming = TextTrimming.CharacterEllipsis });
header.Children.Add(new TextBlock { Text = $"{triggers.Count(x => x.Enabled)} 个触发器", Opacity = .6, FontSize = 12 });
items.Children.Add(new Expander { Header = header, Tag = workflow.Id, Content = content, IsExpanded = expanded.Contains(workflow.Id), HorizontalAlignment = HorizontalAlignment.Stretch, HorizontalContentAlignment = HorizontalAlignment.Stretch });
}
if (items.Children.Count == 0) items.Children.Add(new TextBlock { Text = "没有匹配的工作流", Margin = new(12) });
}
}