diff --git a/AIStudio.Wpf.ADiagram/Demos/Flowchart/FlowchartService.cs b/AIStudio.Wpf.ADiagram/Demos/Flowchart/FlowchartService.cs index 9e8dc4d..a2a3ddc 100644 --- a/AIStudio.Wpf.ADiagram/Demos/Flowchart/FlowchartService.cs +++ b/AIStudio.Wpf.ADiagram/Demos/Flowchart/FlowchartService.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Windows; using System.Windows.Media; using Util.DiagramDesigner; @@ -46,13 +47,243 @@ namespace AIStudio.Wpf.ADiagram.Demos.Flowchart } } - public static void Approve(FlowNode flowNode, int status, string remark) + + + public static List FlowNodes { get; set; } + + + /// + /// 初始化数据 + /// + /// + /// + /// + public static void InitOAData(List oASteps, List connectors) + { + foreach (var edge in connectors) + { + var source = oASteps.FirstOrDefault(p => p.BottomConnector == edge.SourceConnectorInfo || p.LeftConnector == edge.SourceConnectorInfo || p.RightConnector == edge.SourceConnectorInfo); + if (source != null) + { + if (source.Kind == NodeKinds.Decide) + { + source.SelectNextStep.Add((edge.SinkConnectorInfo as FullyCreatedConnectorInfo).DataItem.Id.ToString(), "data.Flag" + edge.Text); + } + else if (source.Kind == NodeKinds.COBegin) + { + source.SelectNextStep.Add((edge.SinkConnectorInfo as FullyCreatedConnectorInfo).DataItem.Id.ToString(), "True"); + } + else + { + source.NextStepId = (edge.SinkConnectorInfo as FullyCreatedConnectorInfo).DataItem.Id.ToString(); + } + } + } + + foreach (var step in oASteps) + { + //恢复指向上一个节点 + if (!string.IsNullOrEmpty(step.NextStepId)) + { + var nextstep = oASteps.FirstOrDefault(p => p.Id.ToString() == step.NextStepId); + if (nextstep == null) + throw new Exception(string.Format("流程异常,无法找到{0}的下一个流程节点{1}", step.Id, step.NextStepId)); + if (nextstep.Kind == NodeKinds.Decide) + { + var nsteps = oASteps.Where(p => nextstep.SelectNextStep.Any(q => p.Id.ToString() == q.Key)); + if (nsteps == null || nsteps.Count() == 0) + throw new Exception(string.Format("流程异常,无法找到{0}的下一个流程节点{1}", step.Id, step.NextStepId)); + + //跳过Decide指向下面的子节点 + foreach (var nstep in nsteps) + { + if (nstep.PreStepId == null) + nstep.PreStepId = new List(); + nstep.PreStepId.Add(step.Id.ToString()); + } + } + else + { + if (nextstep.PreStepId == null) + nextstep.PreStepId = new List(); + nextstep.PreStepId.Add(step.Id.ToString()); + } + } + } + + var oAStartStep = oASteps.Single(p => p.Kind == NodeKinds.Start); + if (string.IsNullOrEmpty(oAStartStep.NextStepId)) + { + throw new Exception("开始节点没有下一个节点"); + } + + string nextstepid = oAStartStep.NextStepId; + FlowNodes = InitStep(oASteps, nextstepid); + FlowNodes.Insert(0, oAStartStep); + + Approve(oAStartStep, 100); + } + + + /// + /// 获取下一个节点 + /// + /// + /// + /// + public static List InitStep(List oASteps, string nextstepid) + { + List outsteps = new List(); + List nextids = new List(); + var step = oASteps.FirstOrDefault(p => p.Id.ToString() == nextstepid); + if (step != null) + { + if (!string.IsNullOrEmpty(step.NextStepId)) + { + nextids.Add(step.NextStepId); + } + else if (step.SelectNextStep != null && step.SelectNextStep.Count > 0) + { + nextids.AddRange(step.SelectNextStep.Keys); + } + + outsteps.Add(step); + oASteps.Remove(step); + } + + int index = outsteps.IndexOf(step); + + nextids.Reverse(); + foreach (var next in nextids) + { + outsteps.InsertRange(index + 1, InitStep(oASteps, next)); + } + return outsteps; + } + + public static void Approve(FlowNode flowNode, int status, string remark = null) { - flowNode.Status = status; switch (status) { case 100: - flowNode.Color = Colors.Green.ToString(); + SetStatus(flowNode, status, remark); + flowNode.Color = Colors.Green.ToString(); + if (!string.IsNullOrEmpty(flowNode.NextStepId)) + { + Next(flowNode.NextStepId); + } + else if (flowNode.SelectNextStep != null && flowNode.SelectNextStep.Count > 0) + { + foreach (var step in flowNode.SelectNextStep) + { + Next(step.Key); + } + } + break; + case 2: + if (Pre(flowNode)) + { + SetStatus(flowNode, status, remark); + } + else + { + MessageBox.Show("该节点不支持驳回上一级"); + } + break; + case 3: + SetStatus(flowNode, status, remark); + FlowNodes.ForEach(p => { if (p.Status == 100) p.Status = 0; }); + Approve(FlowNodes[0], 100); + MessageBox.Show("流程重新开始"); + break; + case 4: + SetStatus(flowNode, status, remark); + MessageBox.Show("流程否决"); + break; + } + } + + public static void Next(string stepid) + { + FlowNode nextNode = FlowNodes.FirstOrDefault(p => p.Id.ToString() == stepid); + SetStatus(nextNode, 1); + + switch (nextNode.Kind) + { + case NodeKinds.Start: + SetStatus(nextNode, 100); + Next(nextNode.NextStepId); + break; + case NodeKinds.End: + SetStatus(nextNode, 100); + MessageBox.Show("流程完成"); + break; + case NodeKinds.Decide: + foreach (var step in nextNode.SelectNextStep) + { + try + { + //暂未实现表达式比较 + step.Value.Replace("data.Flag", nextNode.Text); + //先按第一个表达式成立处理。 + SetStatus(nextNode, 100); + Next(step.Key); + break; + } + catch { } + } + break; + case NodeKinds.COBegin: + foreach (var step in nextNode.SelectNextStep) + { + SetStatus(nextNode, 100); + Next(step.Key); + } + break; + case NodeKinds.COEnd: + foreach (var prestep in nextNode.PreStepId) + { + var step = FlowNodes.FirstOrDefault(p => p.Id.ToString() == prestep); + if (step.Status != 100) + { + return; + } + } + SetStatus(nextNode, 100); + Next(nextNode.NextStepId); + break; + } + } + + public static bool Pre(FlowNode flowNode) + { + if (flowNode.PreStepId != null && flowNode.PreStepId.Count == 1) + { + FlowNode preNode = FlowNodes.FirstOrDefault(p => p.Id.ToString() == flowNode.PreStepId[0]); + if (preNode.Kind == NodeKinds.Middle) + { + SetStatus(preNode, 1); + return true; + } + } + + return false; + } + + public static void SetStatus(FlowNode flowNode, int status, string remark = null) + { + flowNode.Status = status; + flowNode.Remark = remark; + switch (status) + { + case 100: + flowNode.Color = Colors.Green.ToString(); + break; + case 0: + flowNode.Color = Colors.Yellow.ToString(); + break; + case 1: + flowNode.Color = Colors.Orange.ToString(); break; case 2: flowNode.Color = Colors.Red.ToString(); @@ -65,7 +296,5 @@ namespace AIStudio.Wpf.ADiagram.Demos.Flowchart break; } } - - } } diff --git a/AIStudio.Wpf.ADiagram/Demos/Flowchart/FlowchartViewModel.cs b/AIStudio.Wpf.ADiagram/Demos/Flowchart/FlowchartViewModel.cs index 69e8582..c821ad8 100644 --- a/AIStudio.Wpf.ADiagram/Demos/Flowchart/FlowchartViewModel.cs +++ b/AIStudio.Wpf.ADiagram/Demos/Flowchart/FlowchartViewModel.cs @@ -36,13 +36,13 @@ namespace AIStudio.Wpf.ADiagram.Demos.Flowchart { base.Init(); - DesignerItemViewModelBase start = new StartFlowNode() { Left = 100, Top = 0, Color = Colors.Green.ToString() }; + DesignerItemViewModelBase start = new StartFlowNode() { Left = 100, Top = 0, Color = Colors.Yellow.ToString() }; DiagramViewModel.DirectAddItemCommand.Execute(start); DesignerItemViewModelBase middle1 = new MiddleFlowNode() { Left = 100, Top = 100, Color = Colors.Yellow.ToString(), Text = "主管审批" }; DiagramViewModel.DirectAddItemCommand.Execute(middle1); - DesignerItemViewModelBase decide = new DecideFlowNode() { Left = 100, Top = 200, Color = Colors.Yellow.ToString(), Text = "条件" }; + DesignerItemViewModelBase decide = new DecideFlowNode() { Left = 100, Top = 200, Color = Colors.Yellow.ToString(), Text = "5" }; DiagramViewModel.DirectAddItemCommand.Execute(decide); DesignerItemViewModelBase middle2 = new MiddleFlowNode() { Left = 200, Top = 300, Color = Colors.Yellow.ToString(), Text = "分管领导" }; @@ -96,6 +96,8 @@ namespace AIStudio.Wpf.ADiagram.Demos.Flowchart DiagramViewModel.DirectAddItemCommand.Execute(connector10); DiagramViewModel.ClearSelectedItems(); + + FlowchartService.InitOAData(DiagramViewModel.Items.OfType().ToList(), DiagramViewModel.Items.OfType().ToList()); } diff --git a/AIStudio.Wpf.ADiagram/Demos/Flowchart/ViewModels/FlowNode.cs b/AIStudio.Wpf.ADiagram/Demos/Flowchart/ViewModels/FlowNode.cs index e7635d6..1315806 100644 --- a/AIStudio.Wpf.ADiagram/Demos/Flowchart/ViewModels/FlowNode.cs +++ b/AIStudio.Wpf.ADiagram/Demos/Flowchart/ViewModels/FlowNode.cs @@ -1,4 +1,5 @@ using AIStudio.Wpf.ADiagram.Helpers; +using AIStudio.Wpf.ADiagram.Services; using System; using System.Collections.Generic; using System.ComponentModel; @@ -12,11 +13,12 @@ namespace AIStudio.Wpf.ADiagram.Demos.Flowchart { public class FlowNode : DesignerItemViewModelBase { + protected IUIVisualizerService visualiserService; + public FlowNode(NodeKinds kind) : base() { Kind = kind; - Text = Kind.GetDescription(); - ShowText = true; + Text = Kind.GetDescription(); ItemWidth = 80; ItemHeight = 40; @@ -32,6 +34,10 @@ namespace AIStudio.Wpf.ADiagram.Demos.Flowchart base.Init(); ShowRotate = false; + ShowText = true; + IsReadOnlyText = true; + + visualiserService = ApplicationServicesProvider.Instance.Provider.VisualizerService; } protected override void LoadDesignerItemViewModel(IDiagramViewModel parent, SelectableDesignerItemBase designerbase) @@ -68,7 +74,7 @@ namespace AIStudio.Wpf.ADiagram.Demos.Flowchart [Browsable(false)] public string StateImage { get; set; } - #region 没有存起来,仅仅测试使用 + #region 没有存起来,仅仅测试使用,实际这些代码应该都在服务端 private int _status; public int Status @@ -89,6 +95,10 @@ namespace AIStudio.Wpf.ADiagram.Demos.Flowchart SetProperty(ref _remark, value); } } + + public List PreStepId { get; set; } + public string NextStepId { get; set; } + public Dictionary SelectNextStep { get; set; } = new Dictionary(); #endregion } diff --git a/AIStudio.Wpf.ADiagram/Demos/Flowchart/ViewModels/FlowNode.xaml b/AIStudio.Wpf.ADiagram/Demos/Flowchart/ViewModels/FlowNode.xaml index a2ac8ef..341f993 100644 --- a/AIStudio.Wpf.ADiagram/Demos/Flowchart/ViewModels/FlowNode.xaml +++ b/AIStudio.Wpf.ADiagram/Demos/Flowchart/ViewModels/FlowNode.xaml @@ -42,8 +42,14 @@ + + + + + + @@ -109,7 +115,7 @@ - + @@ -126,4 +132,18 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AIStudio.Wpf.ADiagram/Demos/Flowchart/ViewModels/MiddleFlowNode.cs b/AIStudio.Wpf.ADiagram/Demos/Flowchart/ViewModels/MiddleFlowNode.cs index 53d6caf..cfc9373 100644 --- a/AIStudio.Wpf.ADiagram/Demos/Flowchart/ViewModels/MiddleFlowNode.cs +++ b/AIStudio.Wpf.ADiagram/Demos/Flowchart/ViewModels/MiddleFlowNode.cs @@ -1,10 +1,7 @@ using AIStudio.Wpf.ADiagram.Controls; -using System; using System.Collections.Generic; using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Windows; using Util.DiagramDesigner; namespace AIStudio.Wpf.ADiagram.Demos.Flowchart @@ -56,5 +53,25 @@ namespace AIStudio.Wpf.ADiagram.Demos.Flowchart SetProperty(ref _actType, value); } } + + protected override void ExecuteEditCommand(object param) + { + if (IsReadOnly == true) return; + + if (Status == 1) + { + MiddleFlowNodeData data = new MiddleFlowNodeData(); + if (visualiserService.ShowDialog(data) == true) + { + FlowchartService.Approve(this, data.Status, data.Remark); + } + } + else + { + MessageBox.Show("该节点不能进行审批!!!"); + } + } + + } } diff --git a/AIStudio.Wpf.ADiagram/Demos/Flowchart/ViewModels/MiddleFlowNodeData.cs b/AIStudio.Wpf.ADiagram/Demos/Flowchart/ViewModels/MiddleFlowNodeData.cs new file mode 100644 index 0000000..92d7e3c --- /dev/null +++ b/AIStudio.Wpf.ADiagram/Demos/Flowchart/ViewModels/MiddleFlowNodeData.cs @@ -0,0 +1,38 @@ +using AIStudio.Wpf.ADiagram.Models; + +namespace AIStudio.Wpf.ADiagram.Demos.Flowchart +{ + public class MiddleFlowNodeData : TitleBindableBase + { + public MiddleFlowNodeData() + { + Title = "审批"; + } + + private int _status = 100; + public int Status + { + get + { + return _status; + } + set + { + SetProperty(ref _status, value); + } + } + + private string _remark; + public string Remark + { + get + { + return _remark; + } + set + { + SetProperty(ref _remark, value); + } + } + } +} diff --git a/AIStudio.Wpf.ADiagram/Demos/Flowchart/Views/ApproveWindow.xaml b/AIStudio.Wpf.ADiagram/Demos/Flowchart/Views/ApproveWindow.xaml deleted file mode 100644 index a8380b9..0000000 --- a/AIStudio.Wpf.ADiagram/Demos/Flowchart/Views/ApproveWindow.xaml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - diff --git a/AIStudio.Wpf.ADiagram/Demos/Flowchart/Views/ApproveWindow.xaml.cs b/AIStudio.Wpf.ADiagram/Demos/Flowchart/Views/ApproveWindow.xaml.cs deleted file mode 100644 index 82b2380..0000000 --- a/AIStudio.Wpf.ADiagram/Demos/Flowchart/Views/ApproveWindow.xaml.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -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.Shapes; -using Util.DiagramDesigner; - -namespace AIStudio.Wpf.ADiagram.Demos.Flowchart.Views -{ - /// - /// ApproveWindow.xaml 的交互逻辑 - /// - public partial class ApproveWindow : Window - { - public ApproveWindow() - { - InitializeComponent(); - } - } - - public class ApproveWindowViewModel : BindableBase - { - private int _status; - public int Status - { - get - { - return _status; - } - set - { - SetProperty(ref _status, value); - } - } - - private string _remark; - public string Remark - { - get - { - return _remark; - } - set - { - SetProperty(ref _remark, value); - } - } - } -} diff --git a/Util.DiagramDesigner/Converters/InvertBoolConverter.cs b/Util.DiagramDesigner/Converters/InvertBoolConverter.cs new file mode 100644 index 0000000..365c3cd --- /dev/null +++ b/Util.DiagramDesigner/Converters/InvertBoolConverter.cs @@ -0,0 +1,30 @@ +using System; +using System.Globalization; +using System.Windows.Data; +using System.Windows.Markup; + +namespace Util.DiagramDesigner +{ + public class InvertBoolConverter : MarkupExtension, IValueConverter + { + + /// + /// Returns the value for the target property of this markup extension. + /// + /// Object that can provide services for the markup extension. + /// Reference to the instance of this Int32IndexToNumberConverter. + public override object ProvideValue(IServiceProvider serviceProvider) + { + return this; + } + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return !(bool)value; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return !(bool)value; + } + } +} diff --git a/Util.DiagramDesigner/UserControls/DiagramControl.xaml b/Util.DiagramDesigner/UserControls/DiagramControl.xaml index 6ab6d37..e7ad1f8 100644 --- a/Util.DiagramDesigner/UserControls/DiagramControl.xaml +++ b/Util.DiagramDesigner/UserControls/DiagramControl.xaml @@ -22,7 +22,8 @@ - + +