Imports System.Drawing Imports System.Text Imports System.Xml Imports UTS_Core.UTSModule.Production Imports UTS_Core.UTSModule.Test.Command Namespace UTSModule.Station Public NotInheritable Class RowNode #Region "初始化" Sub New() RowType = RowTypeEnum.Flow AuthByType(RowType) Pause = False Action = True RecordName = String.Empty Retry = 0 RetryInterval = 100 [Label] = String.Empty Description = String.Empty ErrorCode = String.Empty ErrorMessage = String.Empty CommandType = String.Empty Command = String.Empty Parameters = New List(Of TestCmdParam) SaveToDb = False ControlType = String.Empty Children = New List(Of RowNode)() Expanded = True AllChildCount = 0 RowNodes = New RowNodeCollection(Me) RowListIndex = 0 RowList = New List(Of RowNode)() RowList.Add(Me) End Sub ''' ''' 模块名称 ''' ''' Public Property [Label] As String ''' ''' 控制命令类型 ''' ''' Public Property ControlType As String ''' ''' 当前流程步骤的解释 ''' ''' Public Property Description As String ''' ''' 调试模式下运行到当前节点后,暂停运行 ''' ''' Public Property Pause() As Boolean ''' ''' 当前流程步骤是否允许执行 ''' ''' Public Property Action As Boolean ''' ''' 当前流程步骤是否会被执行 ''' ''' Public Property IsRunning As Boolean ''' ''' 当前流程步骤执行结果是否保存至数据库,FALSE则为临时变量 ''' ''' Public Property SaveToDb() As Boolean Public Property RecordName As String Public Property Retry As Integer Public Property RetryInterval As Integer Public Property ErrorCode As String Public Property ErrorMessage As String Public Property CommandType As String Public Property Command As String Public Property Parameters() As List(Of TestCmdParam) Private _rowType As RowTypeEnum ''' ''' 行的类型 ''' ''' Public Property RowType As RowTypeEnum Get Return _rowType End Get Set _rowType = Value AuthByType(Value) End Set End Property ''' ''' 行节点关联的站流程 ''' ''' Public Property StationPlan() As StationTestPlan ''' ''' 行节点执行结果信息 ''' ''' Public Property TestReturn As TestCommandReturn ''' ''' 节点树的所有节点集合 ''' ''' Public Property RowList As List(Of RowNode) ''' ''' 节点所属节点数组的位置,从0开始,即头结点的的索引 ''' ''' Public Property RowListIndex() As Integer ''' ''' 节点的级别,可见节点级别从0开始 ''' ''' Public Property RowLever As Integer ''' ''' 节点在父节点中的索引,可见节点级别从0开始 ''' ''' Public Property RowIndex As Integer ''' ''' 记录总使用的说明内容 ''' ''' Public Property Desc4Record As String ''' ''' 子节点总数 ''' ''' Public ReadOnly Property Count() As Integer Get Return Children.Count End Get End Property ''' ''' 所有子节点总数 ''' ''' Public Property AllChildCount() As Integer ''' ''' 行下包含的子行集合 ''' ''' Public Property RowNodes() As RowNodeCollection ''' ''' 当前节点的同级上一节点,若当前节点为首节点则返回nothing ''' ''' Public Property PrevNode() As RowNode ''' ''' 当前节点的同级下一节点,若当前节点为尾节点则返回nothing ''' ''' Public Property NextNode() As RowNode ''' ''' 当前节点的父节点 ''' ''' Public Property ParentNode() As RowNode ''' ''' 当前节点树的起始节点 ''' ''' Public Property HeadNode() As RowNode ''' ''' 内部缓存子节点 ''' Friend Children As List(Of RowNode) ''' ''' 处于展开状态 ''' ''' Public Property Expanded() As Boolean ''' ''' 是否允许删除当前节点 ''' ''' Public Property CanDelete() As Boolean ''' ''' 是否允许添加子节点 ''' ''' Public Property CanAddChildNode() As Boolean ''' ''' 允许操作当前节点内容 ''' ''' Public Property CanChangeContent() As Boolean ''' ''' 允许移动节点改变节点的级别 ''' ''' Public Property CanChangeLever() As Boolean ''' ''' 允许移动节点移动 ''' ''' Public Property CanMove() As Boolean ''' ''' 当前节点是否处于重试状态 ''' ''' Public Property IsRetry As Boolean Private Sub AuthByType(type As RowTypeEnum) Select Case type Case RowTypeEnum.FixedModule CanAddChildNode = True CanChangeContent = False CanDelete = False CanChangeLever = False CanMove = False Case RowTypeEnum.Module CanAddChildNode = True CanChangeContent = True CanDelete = True CanChangeLever = True CanMove = True Case RowTypeEnum.Control CanAddChildNode = True CanChangeContent = True CanDelete = True CanChangeLever = True CanMove = True Case RowTypeEnum.Flow CanAddChildNode = True CanChangeContent = True CanDelete = True CanChangeLever = True CanMove = True End Select End Sub #End Region #Region "节点操作" ''' ''' 展开节点 ''' Public Sub Expand() If Expanded Then Return Expanded = True End Sub ''' ''' 折叠节点 ''' Public Sub Collapse() If Expanded = False Then Return Expanded = False End Sub ''' ''' 展开或折叠节点 ''' Public Sub Toggle() Expanded = Not Expanded End Sub ''' ''' 增加子节点 ''' Public Sub AddNode(node As RowNode) If CanAddChildNode Then RowNodes.Add(node) Else ParentNode.InsertNode(RowIndex + 1, node) End If End Sub ''' ''' 插入子节点 ''' Public Sub InsertNode(index As Integer, childNode As RowNode) If CanAddChildNode Then RowNodes.Insert(index, childNode) Else ParentNode.InsertNode(index, childNode) End If ' ParentNode.InsertNode(index, childNode) End Sub Public Sub RemoveChildNode(childNode As RowNode) If childNode.CanDelete = False Then Return RowNodes.Remove(childNode) End Sub Public Sub RemoveChildAt(index As Integer) If index >= RowNodes.Count Then Return Dim child As RowNode = CType(RowNodes.Item(index), RowNode) If child.CanDelete = False Then Return RowNodes.RemoveAt(index) End Sub ''' ''' 移除本身节点 ''' Public Function Remove() As Boolean ' If CanDelete = False Then Return False ParentNode.RowNodes.Remove(Me) Return True End Function ''' ''' 清空节点所有子节点 ''' Public Sub Clear() RowNodes.Clear() End Sub ''' ''' 节点上移 ''' Public Sub MoveUp() If RowIndex = 0 Then Return If Remove() = False Then Return ParentNode.RowNodes.Insert(RowIndex - 1, Me) End Sub ''' ''' 节点下移 ''' Public Sub MoveDown() If RowIndex = ParentNode.RowNodes.Count - 1 Then Return If Remove() = False Then Return ParentNode.RowNodes.Insert(RowIndex + 1, Me) End Sub ''' ''' 节点左移 ''' Public Sub MoveLeft() If RowLever = 0 Then Return If Remove() = False Then Return ParentNode.ParentNode.RowNodes.Insert(ParentNode.RowIndex + 1, Me) End Sub ''' ''' 节点右移 ''' Public Sub MoveRight() If RowIndex = 0 Then Return ' If CanChangeLever = False Then Return If Remove() = False Then Return Dim rNode As RowNode = CType(ParentNode.RowNodes(RowIndex - 1), RowNode) rNode.RowNodes.Add(Me) End Sub ''' ''' 节点深复制,创建一个完全相同信息的节点 ''' ''' Public Function Clone() As RowNode Dim cpNode As New RowNode With cpNode .RowListIndex = RowListIndex .Pause = Pause .ControlType = ControlType .SaveToDb = SaveToDb .RowType = RowType .Action = Action .RecordName = RecordName .Retry = Retry .RetryInterval = RetryInterval .[Label] = String.Copy(Label) .Description = String.Copy(Description) .ErrorCode = String.Copy(ErrorCode) .ErrorMessage = String.Copy(ErrorMessage) .CommandType = String.Copy(CommandType) .Command = String.Copy(Command) .Parameters = New List(Of TestCmdParam) For Each param As TestCmdParam In Parameters .Parameters.Add(param.Clone()) Next '.RowNodes = New RowNodeCollection(cpNode) '.Children = New List(Of RowNode)() ''todo:克隆功能待重写 'For Each child As RowNode In Children ' .RowNodes.Add(child.Clone()) 'Next End With Return cpNode End Function Public Sub CopyFrom(node As RowNode) With node .RowListIndex = RowListIndex Pause = .Pause ControlType = .ControlType SaveToDb = .SaveToDb RowType = .RowType Action = .Action RecordName = .RecordName Retry = .Retry RetryInterval = .RetryInterval [Label] = String.Copy(.Label) Description = String.Copy(.Description) ErrorCode = String.Copy(.ErrorCode) ErrorMessage = String.Copy(.ErrorMessage) CommandType = String.Copy(.CommandType) Command = String.Copy(.Command) Parameters.Clear() For Each param As TestCmdParam In .Parameters Parameters.Add(param.Clone()) Next End With End Sub #End Region #Region "节点样式" Public Enum RowTypeEnum ''' ''' 固定模块 ''' FixedModule ''' ''' 模块,可以当作跳转入口 ''' [Module] ''' ''' 控制 ''' Control ''' ''' 流程 ''' Flow End Enum #End Region #Region "节点风格" Public Shared Property NodeStyles() As Dictionary(Of RowTypeEnum, RowNodeStyle) ''' ''' 默认的初始化节点风格 ''' Public Shared Sub InitNodeStyles() NodeStyles = New Dictionary(Of RowTypeEnum, RowNodeStyle) From { {RowTypeEnum.FixedModule, New RowNodeStyle(RowTypeEnum.FixedModule)}, {RowTypeEnum.Module, New RowNodeStyle(RowTypeEnum.Module)}, {RowTypeEnum.Control, New RowNodeStyle(RowTypeEnum.Control)}, {RowTypeEnum.Flow, New RowNodeStyle(RowTypeEnum.Flow)} } End Sub Private Shared Function LoadNodeStyle(nodeList As XmlNodeList) As RowNodeStyle Dim nodeStyle As New RowNodeStyle Dim xe As XmlElement For Each node As XmlNode In nodeList xe = CType(node, XmlElement) Select Case xe.LocalName Case "Font" Dim fStyle As FontStyle = CType([Enum].Parse(GetType(FontStyle), xe.GetAttribute("FontStyle")), FontStyle) Dim fSize As Single = CSng(xe.GetAttribute("FontSize")) nodeStyle.NodeFont = New Font(xe.InnerText, fSize, fStyle) Case "ForeColor" nodeStyle.NodeForeColor = Color.FromArgb(CInt(xe.InnerText)) Case "BackColor" nodeStyle.NodeBackColor = Color.FromArgb(CInt(xe.InnerText)) Case "ImageKey" nodeStyle.NodeImageKey = xe.InnerText Case "ShowRecord" nodeStyle.ShowRecord = CType(xe.InnerText, Boolean) Case "ShowLabel" nodeStyle.ShowLabel = CType(xe.InnerText, Boolean) Case "ShowDescription" nodeStyle.ShowDescription = CType(xe.InnerText, Boolean) Case "ShowAction" nodeStyle.ShowAction = CType(xe.InnerText, Boolean) Case "ShowRecord" nodeStyle.ShowRecord = CType(xe.InnerText, Boolean) Case "ShowRetry" nodeStyle.ShowRetry = CType(xe.InnerText, Boolean) Case "ShowRetryInterval" nodeStyle.ShowRetryInterval = CType(xe.InnerText, Boolean) Case "ShowErrorCode" nodeStyle.ShowErrorCode = CType(xe.InnerText, Boolean) Case "ShowErrorMessage" nodeStyle.ShowErrorMessage = CType(xe.InnerText, Boolean) Case "ShowCommand" nodeStyle.ShowCommand = CType(xe.InnerText, Boolean) Case "ShowParameter" nodeStyle.ShowParameter = CType(xe.InnerText, Boolean) Case Else Throw New Exception($"LoadRowNodes Unknown LocalName:{xe.LocalName}") End Select Next Return nodeStyle End Function ''' ''' 从本地文件中初始化节点风格 ''' ''' Public Shared Sub LoadNodeStyles(path As String) NodeStyles = New Dictionary(Of RowTypeEnum, RowNodeStyle)() Dim xd As New XmlDocument() xd.Load(path) Dim xe As XmlElement Dim nodeList As XmlNodeList = xd.SelectSingleNode($"NodeStyles").ChildNodes For Each node As XmlNode In nodeList xe = CType(node, XmlElement) Select Case xe.LocalName Case "NodeStyle" Dim type As RowTypeEnum = CType([Enum].Parse(GetType(RowTypeEnum), xe.GetAttribute("Type")), RowTypeEnum) NodeStyles.Add(type, LoadNodeStyle(xe.ChildNodes)) Case Else Throw New Exception($"LoadNodeStyles Unknown LocalName:{xe.LocalName}") End Select Next End Sub Public Shared Sub SaveNodeStyles(path As String) Dim xws As New XmlWriterSettings With xws .Indent = True .NewLineOnAttributes = False .Encoding = New UTF8Encoding(False) End With Using xw As XmlWriter = XmlWriter.Create(path, xws) xw.WriteStartDocument() xw.WriteStartElement($"NodeStyles") '创建跟节点 For Each nodeStyle As KeyValuePair(Of RowTypeEnum, RowNodeStyle) In NodeStyles xw.WriteStartElement($"NodeStyle") '创建表属性节点 xw.WriteAttributeString("Type", nodeStyle.Key.ToString()) xw.WriteStartElement($"Font") '创建表属性节点 xw.WriteAttributeString("FontSize", nodeStyle.Value.NodeFont.Size.ToString()) xw.WriteAttributeString("FontStyle", nodeStyle.Value.NodeFont.Style.ToString()) xw.WriteString(nodeStyle.Value.NodeFont.Name.ToString()) xw.WriteEndElement() xw.WriteElementString("ForeColor", nodeStyle.Value.NodeForeColor.ToArgb().ToString()) xw.WriteElementString("BackColor", nodeStyle.Value.NodeBackColor.ToArgb().ToString()) xw.WriteElementString("ImageKey", nodeStyle.Value.NodeImageKey) If nodeStyle.Value.ShowRowType Then xw.WriteElementString("ShowRecord", nodeStyle.Value.ShowRowType.ToString()) If nodeStyle.Value.ShowLabel Then xw.WriteElementString("ShowLabel", nodeStyle.Value.ShowLabel.ToString()) If nodeStyle.Value.ShowDescription Then xw.WriteElementString("ShowDescription", nodeStyle.Value.ShowDescription.ToString()) If nodeStyle.Value.ShowAction Then xw.WriteElementString("ShowAction", nodeStyle.Value.ShowAction.ToString()) If nodeStyle.Value.ShowRecord Then xw.WriteElementString("ShowRecord", nodeStyle.Value.ShowRecord.ToString()) If nodeStyle.Value.ShowRetry Then xw.WriteElementString("ShowRetry", nodeStyle.Value.ShowRetry.ToString()) If nodeStyle.Value.ShowRetryInterval Then xw.WriteElementString("ShowRetryInterval", nodeStyle.Value.ShowRetryInterval.ToString()) If nodeStyle.Value.ShowErrorCode Then xw.WriteElementString("ShowErrorCode", nodeStyle.Value.ShowErrorCode.ToString()) If nodeStyle.Value.ShowErrorMessage Then xw.WriteElementString("ShowErrorMessage", nodeStyle.Value.ShowErrorMessage.ToString()) If nodeStyle.Value.ShowCommand Then xw.WriteElementString("ShowCommand", nodeStyle.Value.ShowCommand.ToString()) If nodeStyle.Value.ShowParameter Then xw.WriteElementString("ShowParameter", nodeStyle.Value.ShowParameter.ToString()) xw.WriteEndElement() Next xw.WriteEndElement() xw.WriteEndDocument() End Using End Sub #End Region #Region "节点保存与加载" Public Sub SaveRowNode(xw As XmlWriter) xw.WriteStartElement($"RowNode") '创建单元格节点 xw.WriteElementString("RowType", RowType.ToString()) If String.IsNullOrEmpty(Label) = False Then xw.WriteElementString("Label", Label) xw.WriteElementString("Action", Action.ToString()) If String.IsNullOrEmpty(ControlType) = False Then xw.WriteElementString("ControlType", ControlType) If String.IsNullOrEmpty(CommandType) = False Then xw.WriteElementString("CommandType", CommandType) If String.IsNullOrEmpty(Command) = False Then xw.WriteElementString("Command", Command) If String.IsNullOrEmpty(Description) = False Then xw.WriteElementString("Description", Description) xw.WriteElementString("Retry", Retry.ToString()) xw.WriteElementString("RetryInterval", RetryInterval.ToString()) xw.WriteElementString("SaveToDb", SaveToDb.ToString()) If String.IsNullOrEmpty(RecordName) = False Then xw.WriteElementString("RecordName", RecordName) If String.IsNullOrEmpty(ErrorCode) = False Then xw.WriteElementString("ErrorCode", ErrorCode) If String.IsNullOrEmpty(ErrorMessage) = False Then xw.WriteElementString("ErrorMessage", ErrorMessage) For Each parameter As TestCmdParam In Parameters xw.WriteStartElement($"Parameter") '创建跟节点 xw.WriteAttributeString("Type", parameter.Type) xw.WriteAttributeString("Desc", parameter.Desc) xw.WriteAttributeString("LowerLimit", parameter.LowerLimit) xw.WriteAttributeString("UpperLimit", parameter.UpperLimit) xw.WriteString(parameter.Value) xw.WriteEndElement() Next If RowNodes.Count > 0 Then SaveRowNodes(xw, RowNodes) End If xw.WriteEndElement() End Sub Public Shared Sub SaveRowNodes(xw As XmlWriter, nodes As RowNodeCollection) xw.WriteStartElement($"RowNodes") '创建单元格节点 For Each node As RowNode In nodes node.SaveRowNode(xw) Next xw.WriteEndElement() End Sub ''' ''' 导出为XML文件 ''' ''' 文件路径 Public Sub ExportToXml(path As String) Dim xws As New XmlWriterSettings With xws .Indent = True .NewLineOnAttributes = False .Encoding = New UTF8Encoding(False) End With Using xw As XmlWriter = XmlWriter.Create(path, xws) xw.WriteStartDocument() SaveRowNode(xw) xw.WriteEndDocument() End Using End Sub ''' ''' 加载行节点 ''' ''' ''' Public Shared Sub LoadRowNodes(nodeList As XmlNodeList, rowCollection As RowNodeCollection) Dim xe As XmlElement For Each node As XmlNode In nodeList xe = CType(node, XmlElement) Select Case xe.LocalName Case "RowNode" Dim row As New RowNode rowCollection.Add(row) row.LoadFormXmlNodeList(xe.ChildNodes) Case Else Throw New Exception($"LoadRowNodes Unknown LocalName:{xe.LocalName}") End Select Next End Sub Public Sub LoadFormXmlNodeList(nodeList As XmlNodeList) Dim xe As XmlElement For Each node As XmlNode In nodeList xe = CType(node, XmlElement) Select Case xe.LocalName Case "RowType" RowType = CType([Enum].Parse(GetType(RowTypeEnum), xe.InnerText), RowTypeEnum) Case "Description" Description = xe.InnerText Case "Label" Label = xe.InnerText Case "ControlType" ControlType = xe.InnerText Case "Action" Action = CBool(xe.InnerText) Case "SaveToDb" SaveToDb = CBool(xe.InnerText) Case "RecordName" RecordName = xe.InnerText Case "Retry" Retry = CInt(xe.InnerText) Case "RetryInterval" RetryInterval = CInt(xe.InnerText) Case "ErrorCode" ErrorCode = xe.InnerText Case "ErrorMessage" ErrorMessage = xe.InnerText Case "CommandType" CommandType = xe.InnerText Case "Command" Command = xe.InnerText Case "Parameter" Dim param As New TestCmdParam With { .Type = xe.GetAttribute("Type"), .Desc = xe.GetAttribute("Desc"), .LowerLimit = xe.GetAttribute("LowerLimit"), .UpperLimit = xe.GetAttribute("UpperLimit"), .Value = xe.InnerText } Parameters.Add(param) Case "RowNodes" RowNodes.Clear() LoadRowNodes(xe.ChildNodes, RowNodes) Case Else Throw New Exception($"LoadRowNode Unknown LocalName:{xe.LocalName}") End Select Next End Sub Public Sub LoadFormXml(path As String) Dim xd As New XmlDocument() xd.Load(path) Dim nodeList As XmlNodeList = xd.SelectSingleNode($"RowNode").ChildNodes LoadFormXmlNodeList(nodeList) End Sub #End Region End Class End Namespace