mirror of
https://gitee.com/akwkevin/aistudio.-wpf.-diagram
synced 2026-04-05 16:56:34 +08:00
结构调整,便于后续扩展
This commit is contained in:
22
AIStudio.Wpf.Flowchart/AIStudio.Wpf.Flowchart.csproj
Normal file
22
AIStudio.Wpf.Flowchart/AIStudio.Wpf.Flowchart.csproj
Normal file
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<UseWPF>true</UseWPF>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MathParser.org-mXparser" Version="4.4.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AIStudio.Wpf.BaseDiagram\AIStudio.Wpf.BaseDiagram.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="ViewModels\FlowNode.xaml">
|
||||
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
365
AIStudio.Wpf.Flowchart/FlowchartService.cs
Normal file
365
AIStudio.Wpf.Flowchart/FlowchartService.cs
Normal file
@@ -0,0 +1,365 @@
|
||||
using AIStudio.Wpf.Flowchart.ViewModels;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using Util.DiagramDesigner;
|
||||
using Expression = org.mariuszgromada.math.mxparser.Expression;
|
||||
|
||||
namespace AIStudio.Wpf.Flowchart
|
||||
{
|
||||
public static class FlowchartService
|
||||
{
|
||||
static FlowchartService()
|
||||
{
|
||||
Users = new List<SelectOption>()
|
||||
{
|
||||
new SelectOption(){ value = "操作员1",text = "操作员1" },
|
||||
new SelectOption(){ value = "操作员2",text = "操作员2" },
|
||||
new SelectOption(){ value = "Admin",text = "Admin" },
|
||||
};
|
||||
|
||||
Roles = new List<SelectOption>()
|
||||
{
|
||||
new SelectOption(){ value = "操作员",text = "操作员" },
|
||||
new SelectOption(){ value = "管理员",text = "管理员" },
|
||||
};
|
||||
}
|
||||
|
||||
private static List<SelectOption> _users;
|
||||
public static List<SelectOption> Users
|
||||
{
|
||||
get { return _users; }
|
||||
set
|
||||
{
|
||||
_users = value;
|
||||
}
|
||||
}
|
||||
|
||||
private static List<SelectOption> _roles;
|
||||
public static List<SelectOption> Roles
|
||||
{
|
||||
get { return _roles; }
|
||||
set
|
||||
{
|
||||
_roles = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 流程数据
|
||||
/// </summary>
|
||||
public static List<FlowNode> FlowNodes { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 初始化数据
|
||||
/// </summary>
|
||||
/// <param name="json"></param>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public static void InitOAData(List<FlowNode> oASteps, List<ConnectorViewModel> 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<string>();
|
||||
nstep.PreStepId.Add(step.Id.ToString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nextstep.PreStepId == null)
|
||||
nextstep.PreStepId = new List<string>();
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 初始化步骤
|
||||
/// </summary>
|
||||
/// <param name="oASteps"></param>
|
||||
/// <param name="nextstepid"></param>
|
||||
/// <returns></returns>
|
||||
public static List<FlowNode> InitStep(List<FlowNode> oASteps, string nextstepid)
|
||||
{
|
||||
List<FlowNode> outsteps = new List<FlowNode>();
|
||||
List<string> nextids = new List<string>();
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 审批动作,因为是客户端模拟,假设每次都是该节点的审批人进行的操作
|
||||
/// </summary>
|
||||
/// <param name="flowNode"></param>
|
||||
/// <param name="status"></param>
|
||||
/// <param name="remark"></param>
|
||||
public static void Approve(FlowNode flowNode, int status, string remark = null)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case 100:
|
||||
if (flowNode is MiddleFlowNode middleFlowNode)
|
||||
{
|
||||
if (string.IsNullOrEmpty(flowNode.Remark))
|
||||
{
|
||||
remark = "审批人:" + remark;
|
||||
}
|
||||
else
|
||||
{
|
||||
remark = flowNode.Remark + "\r审批人:" + remark;
|
||||
}
|
||||
|
||||
if (middleFlowNode.ActType == "and")//如果是与签,那么要都审批通过
|
||||
{
|
||||
if (middleFlowNode.UserIds != null && middleFlowNode.UserIds.Count > 1)
|
||||
{
|
||||
//实际情况不是这样的,这里只是演示,简化。
|
||||
int count = remark.Split("审批人:", StringSplitOptions.RemoveEmptyEntries).Length;
|
||||
if (middleFlowNode.UserIds.Count != count)
|
||||
{
|
||||
SetStatus(flowNode, 1, remark);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (middleFlowNode.RoleIds != null && middleFlowNode.RoleIds.Count > 1)
|
||||
{
|
||||
//实际情况不是这样的,这里只是演示,简化。
|
||||
int count = remark.Split("审批人:", StringSplitOptions.RemoveEmptyEntries).Length;
|
||||
if (middleFlowNode.RoleIds.Count != count)
|
||||
{
|
||||
SetStatus(flowNode, 1, remark);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SetStatus(flowNode, status, remark);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 流向下一个节点
|
||||
/// </summary>
|
||||
/// <param name="stepid"></param>
|
||||
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
|
||||
{
|
||||
//按条件选择一个分支
|
||||
string express = step.Value.Replace("data.Flag", nextNode.Text);
|
||||
Expression e = new Expression(express);
|
||||
var result = e.calculate();
|
||||
if (result == 1)
|
||||
{
|
||||
SetStatus(nextNode, 100);
|
||||
Next(step.Key);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
//如果表达式错了,就按第一个处理
|
||||
Next(nextNode.SelectNextStep.FirstOrDefault().Key);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 流向上一个节点
|
||||
/// </summary>
|
||||
/// <param name="flowNode"></param>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置颜色
|
||||
/// </summary>
|
||||
/// <param name="flowNode"></param>
|
||||
/// <param name="status"></param>
|
||||
/// <param name="remark"></param>
|
||||
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();
|
||||
break;
|
||||
case 3:
|
||||
flowNode.Color = Colors.Red.ToString();
|
||||
break;
|
||||
case 4:
|
||||
flowNode.Color = Colors.Red.ToString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
51
AIStudio.Wpf.Flowchart/Models/FlowNodeDesignerItem.cs
Normal file
51
AIStudio.Wpf.Flowchart/Models/FlowNodeDesignerItem.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using AIStudio.Wpf.Flowchart.ViewModels;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Media;
|
||||
using System.Xml.Serialization;
|
||||
using Util.DiagramDesigner;
|
||||
|
||||
namespace AIStudio.Wpf.Flowchart.Models
|
||||
{
|
||||
public class FlowNodeDesignerItem : DesignerItemBase
|
||||
{
|
||||
public FlowNodeDesignerItem()
|
||||
{
|
||||
|
||||
}
|
||||
public FlowNodeDesignerItem(FlowNode item) : base(item)
|
||||
{
|
||||
if (item is MiddleFlowNode middleFlow)
|
||||
{
|
||||
UserIds = middleFlow.UserIds;
|
||||
RoleIds = middleFlow.RoleIds;
|
||||
ActType = middleFlow.ActType;
|
||||
}
|
||||
Color = item.Color;
|
||||
Kind = item.Kind;
|
||||
StateImage = item.StateImage;
|
||||
}
|
||||
|
||||
[XmlArray]
|
||||
public List<string> UserIds { get; set; }
|
||||
|
||||
[XmlArray]
|
||||
public List<string> RoleIds { get; set; }
|
||||
|
||||
[XmlAttribute]
|
||||
public string ActType { get; set; }
|
||||
|
||||
[XmlAttribute]
|
||||
public string Color { get; set; }
|
||||
|
||||
[XmlAttribute]
|
||||
public NodeKinds Kind { get; set; }
|
||||
|
||||
[XmlAttribute]
|
||||
public string StateImage { get; set; }
|
||||
}
|
||||
}
|
||||
22
AIStudio.Wpf.Flowchart/NodeKinds.cs
Normal file
22
AIStudio.Wpf.Flowchart/NodeKinds.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace AIStudio.Wpf.Flowchart
|
||||
{
|
||||
public enum NodeKinds
|
||||
{
|
||||
[Description("节点")]
|
||||
Normal = 0,
|
||||
[Description("开始")]
|
||||
Start = 1,
|
||||
[Description("结束")]
|
||||
End = 2,
|
||||
[Description("中间节点")]
|
||||
Middle = 3,
|
||||
[Description("条件节点")]
|
||||
Decide = 4,
|
||||
[Description("并行开始")]
|
||||
COBegin = 5,
|
||||
[Description("并行结束")]
|
||||
COEnd = 6,
|
||||
}
|
||||
}
|
||||
16
AIStudio.Wpf.Flowchart/SelectOption.cs
Normal file
16
AIStudio.Wpf.Flowchart/SelectOption.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace AIStudio.Wpf.Flowchart
|
||||
{
|
||||
/// <summary>
|
||||
/// 前端SelectOption
|
||||
/// </summary>
|
||||
public class SelectOption
|
||||
{
|
||||
public string value { get; set; }
|
||||
public string text { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return text;
|
||||
}
|
||||
}
|
||||
}
|
||||
165
AIStudio.Wpf.Flowchart/ViewModels/FlowNode.cs
Normal file
165
AIStudio.Wpf.Flowchart/ViewModels/FlowNode.cs
Normal file
@@ -0,0 +1,165 @@
|
||||
using AIStudio.Wpf.BaseDiagram;
|
||||
using AIStudio.Wpf.BaseDiagram.Services;
|
||||
using AIStudio.Wpf.Flowchart.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using Util.DiagramDesigner;
|
||||
|
||||
namespace AIStudio.Wpf.Flowchart.ViewModels
|
||||
{
|
||||
public class FlowNode : DesignerItemViewModelBase
|
||||
{
|
||||
protected IUIVisualizerService visualiserService;
|
||||
|
||||
public FlowNode(NodeKinds kind) : base()
|
||||
{
|
||||
Kind = kind;
|
||||
Text = Kind.GetDescription();
|
||||
ItemWidth = 80;
|
||||
ItemHeight = 40;
|
||||
|
||||
}
|
||||
|
||||
public FlowNode(IDiagramViewModel parent, DesignerItemBase designer) : base(parent, designer)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override void Init()
|
||||
{
|
||||
base.Init();
|
||||
|
||||
ShowRotate = false;
|
||||
ShowText = true;
|
||||
IsReadOnlyText = true;
|
||||
|
||||
visualiserService = ApplicationServicesProvider.Instance.Provider.VisualizerService;
|
||||
}
|
||||
|
||||
protected override void LoadDesignerItemViewModel(IDiagramViewModel parent, SelectableDesignerItemBase designerbase)
|
||||
{
|
||||
base.LoadDesignerItemViewModel(parent, designerbase);
|
||||
|
||||
FlowNodeDesignerItem designer = designerbase as FlowNodeDesignerItem;
|
||||
this.Color = designer.Color;
|
||||
this.Kind = designer.Kind;
|
||||
this.StateImage = designer.StateImage;
|
||||
|
||||
if (this is MiddleFlowNode middle)
|
||||
{
|
||||
middle.UserIds = designer.UserIds;
|
||||
middle.RoleIds = designer.RoleIds;
|
||||
middle.ActType = designer.ActType;
|
||||
}
|
||||
}
|
||||
|
||||
private string _color;
|
||||
[Browsable(true)]
|
||||
public string Color
|
||||
{
|
||||
get { return _color; }
|
||||
set
|
||||
{
|
||||
SetProperty(ref _color, value);
|
||||
}
|
||||
}
|
||||
|
||||
[Browsable(false)]
|
||||
public NodeKinds Kind { get; set; }
|
||||
|
||||
[Browsable(false)]
|
||||
public string StateImage { get; set; }
|
||||
|
||||
#region 没有存起来,仅仅测试使用,实际这些代码应该都在服务端
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
public List<string> PreStepId { get; set; }
|
||||
public string NextStepId { get; set; }
|
||||
public Dictionary<string, string> SelectNextStep { get; set; } = new Dictionary<string, string>();
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class StartFlowNode : FlowNode
|
||||
{
|
||||
public StartFlowNode() : base(NodeKinds.Start)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public StartFlowNode(IDiagramViewModel parent, DesignerItemBase designer) : base(parent, designer)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class EndFlowNode : FlowNode
|
||||
{
|
||||
public EndFlowNode() : base(NodeKinds.End)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public EndFlowNode(IDiagramViewModel parent, DesignerItemBase designer) : base(parent, designer)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class DecideFlowNode : FlowNode
|
||||
{
|
||||
public DecideFlowNode() : base(NodeKinds.Decide)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public DecideFlowNode(IDiagramViewModel parent, DesignerItemBase designer) : base(parent, designer)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class COBeginFlowNode : FlowNode
|
||||
{
|
||||
public COBeginFlowNode() : base(NodeKinds.COBegin)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public COBeginFlowNode(IDiagramViewModel parent, DesignerItemBase designer) : base(parent, designer)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class COEndFlowNode : FlowNode
|
||||
{
|
||||
public COEndFlowNode() : base(NodeKinds.COEnd)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public COEndFlowNode(IDiagramViewModel parent, DesignerItemBase designer) : base(parent, designer)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
126
AIStudio.Wpf.Flowchart/ViewModels/FlowNode.xaml
Normal file
126
AIStudio.Wpf.Flowchart/ViewModels/FlowNode.xaml
Normal file
@@ -0,0 +1,126 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:s="clr-namespace:Util.DiagramDesigner;assembly=Util.DiagramDesigner"
|
||||
xmlns:viewmodel="clr-namespace:AIStudio.Wpf.Flowchart.ViewModels"
|
||||
xmlns:converter="clr-namespace:AIStudio.Wpf.BaseDiagram.Converters;assembly=AIStudio.Wpf.BaseDiagram">
|
||||
|
||||
<s:ColorBrushConverter x:Key="ColorBrushConverter"/>
|
||||
|
||||
<ControlTemplate x:Key="NormalNodeStyle" TargetType="{x:Type ContentControl}">
|
||||
<Grid>
|
||||
<Border BorderThickness="1" BorderBrush="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}" Background="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}">
|
||||
<Grid>
|
||||
<Border HorizontalAlignment="Left" Width="3" Background="{Binding Color}"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
|
||||
<ControlTemplate x:Key="StartNodeStyle" TargetType="{x:Type ContentControl}">
|
||||
<Grid>
|
||||
<Border CornerRadius="3" BorderThickness="1" BorderBrush="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}" Background="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}">
|
||||
<Grid>
|
||||
<Border HorizontalAlignment="Left" CornerRadius="3,0,0,3" Width="3" Background="{Binding Color}"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
|
||||
<ControlTemplate x:Key="EndNodeStyle" TargetType="{x:Type ContentControl}">
|
||||
<Grid>
|
||||
<Border CornerRadius="3" BorderThickness="1" BorderBrush="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}" Background="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}">
|
||||
<Grid>
|
||||
<Border HorizontalAlignment="Left" CornerRadius="3,0,0,3" Width="3" Background="{Binding Color}"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
|
||||
<ControlTemplate x:Key="MiddleNodeStyle" TargetType="{x:Type ContentControl}">
|
||||
<Grid>
|
||||
<Border BorderThickness="1" BorderBrush="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}" Background="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}">
|
||||
<Grid>
|
||||
<Border HorizontalAlignment="Left" Width="3" Background="{Binding Color}"/>
|
||||
|
||||
</Grid>
|
||||
</Border>
|
||||
<TextBlock Text="{Binding Remark}" FontSize="9" RenderTransformOrigin="1,0.5" TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="2">
|
||||
<TextBlock.RenderTransform>
|
||||
<TranslateTransform X="{Binding ItemWidth}"/>
|
||||
</TextBlock.RenderTransform>
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
|
||||
<ControlTemplate x:Key="DecideNodeStyle" TargetType="{x:Type ContentControl}">
|
||||
<Grid>
|
||||
<Path Stroke="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}" Fill="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}" StrokeThickness="1" Stretch="Fill" Data="M 0,0.25 L 0.5 0 L 1,0.25 L 0.5,0.5 Z"></Path>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
|
||||
|
||||
<ControlTemplate x:Key="COBeginNodeStyle" TargetType="{x:Type ContentControl}">
|
||||
<Grid>
|
||||
<Border BorderThickness="1" BorderBrush="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}" Background="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}">
|
||||
<Grid>
|
||||
<Border HorizontalAlignment="Left" Width="3" Background="{Binding Color}"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
|
||||
<ControlTemplate x:Key="COEndNodeStyle" TargetType="{x:Type ContentControl}">
|
||||
<Grid>
|
||||
<Border BorderThickness="1" BorderBrush="{Binding ColorViewModel.LineColor,Converter={StaticResource ColorBrushConverter}}" Background="{Binding ColorViewModel.FillColor,Converter={StaticResource ColorBrushConverter}}">
|
||||
<Grid>
|
||||
<Border HorizontalAlignment="Left" Width="3" Background="{Binding Color}"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
|
||||
<Style x:Key="CustomFlowNodeStyle" TargetType="{x:Type ContentControl}">
|
||||
<Setter Property="Template" Value="{StaticResource NormalNodeStyle}" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Kind}" Value="Start">
|
||||
<Setter Property="Template" Value="{StaticResource StartNodeStyle}" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Kind}" Value="End">
|
||||
<Setter Property="Template" Value="{StaticResource EndNodeStyle}" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Kind}" Value="Middle">
|
||||
<Setter Property="Template" Value="{StaticResource MiddleNodeStyle}" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Kind}" Value="Decide">
|
||||
<Setter Property="Template" Value="{StaticResource DecideNodeStyle}" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Kind}" Value="COBegin">
|
||||
<Setter Property="Template" Value="{StaticResource COBeginNodeStyle}" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Kind}" Value="COEnd">
|
||||
<Setter Property="Template" Value="{StaticResource COEndNodeStyle}" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<DataTemplate DataType="{x:Type viewmodel:FlowNode}">
|
||||
<Grid IsHitTestVisible="False">
|
||||
<ContentControl Style="{StaticResource CustomFlowNodeStyle}"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate DataType="{x:Type viewmodel:MiddleFlowNodeData}">
|
||||
<Grid Background="{DynamicResource Fluent.Ribbon.Brushes.AccentBaseColorBrush}">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<StackPanel Margin="5" Orientation="Horizontal" >
|
||||
<RadioButton Margin="3" IsChecked="{Binding Status,Converter={converter:ConverterValueMapToBool Parameter=100}, ConverterParameter=100}" Content="通过"/>
|
||||
<RadioButton Margin="3" IsChecked="{Binding Status,Converter={converter:ConverterValueMapToBool Parameter=2}, ConverterParameter=2}" Content="驳回上一级"/>
|
||||
<RadioButton Margin="3" IsChecked="{Binding Status,Converter={converter:ConverterValueMapToBool Parameter=3}, ConverterParameter=3}" Content="驳回重提"/>
|
||||
<RadioButton Margin="3" IsChecked="{Binding Status,Converter={converter:ConverterValueMapToBool Parameter=4}, ConverterParameter=4}" Content="否决"/>
|
||||
</StackPanel>
|
||||
<TextBox Height="28" Margin="5" Text="{Binding Remark}" VerticalContentAlignment="Center"></TextBox>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
</ResourceDictionary>
|
||||
77
AIStudio.Wpf.Flowchart/ViewModels/MiddleFlowNode.cs
Normal file
77
AIStudio.Wpf.Flowchart/ViewModels/MiddleFlowNode.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using AIStudio.Wpf.BaseDiagram.Controls;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using Util.DiagramDesigner;
|
||||
|
||||
namespace AIStudio.Wpf.Flowchart.ViewModels
|
||||
{
|
||||
public class MiddleFlowNode : FlowNode
|
||||
{
|
||||
public MiddleFlowNode() : base(NodeKinds.Middle)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public MiddleFlowNode(IDiagramViewModel parent, DesignerItemBase designer) : base(parent, designer)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private List<string> _userIds = new List<string>();
|
||||
[Browsable(true)]
|
||||
[StyleName("UserIdsStyle")]
|
||||
public List<string> UserIds
|
||||
{
|
||||
get { return _userIds; }
|
||||
set
|
||||
{
|
||||
SetProperty(ref _userIds, value);
|
||||
}
|
||||
}
|
||||
|
||||
private List<string> _roleIds = new List<string>();
|
||||
[Browsable(true)]
|
||||
[StyleName("RoleIdsStyle")]
|
||||
public List<string> RoleIds
|
||||
{
|
||||
get { return _roleIds; }
|
||||
set
|
||||
{
|
||||
SetProperty(ref _roleIds, value);
|
||||
}
|
||||
}
|
||||
|
||||
private string _actType;
|
||||
[Browsable(true)]
|
||||
[StyleName("ActTypeStyle")]
|
||||
public string ActType
|
||||
{
|
||||
get { return _actType; }
|
||||
set
|
||||
{
|
||||
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("该节点不能进行审批!!!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
38
AIStudio.Wpf.Flowchart/ViewModels/MiddleFlowNodeData.cs
Normal file
38
AIStudio.Wpf.Flowchart/ViewModels/MiddleFlowNodeData.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using AIStudio.Wpf.BaseDiagram.Models;
|
||||
|
||||
namespace AIStudio.Wpf.Flowchart.ViewModels
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user