using Avalonia; using Avalonia.Threading; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Cowain.Base.Helpers; using Irihi.Avalonia.Shared.Contracts; using Newtonsoft.Json; using Plugin.Cowain.Wcs.IServices; using Plugin.Cowain.Wcs.Models.Enum; using Plugin.Cowain.Wcs.ViewModels.ProcessGraph; using System.Collections.ObjectModel; using System.Diagnostics; using System.Windows.Input; namespace Plugin.Cowain.Wcs.ViewModels; public partial class ProcessEditDialogViewModel : ObservableObject, IDialogContext { private class FlowDataDto { public List Nodes { get; set; } = new(); public List Connections { get; set; } = new(); } public NodifyObservableCollection Nodes { get; } = new NodifyObservableCollection(); public NodifyObservableCollection Connections { get; } = new(); public PendingConnectionViewModel PendingConnection { get; } public event EventHandler? RequestClose; [ObservableProperty] private StationNodeViewModel? _selectedNode; [ObservableProperty] private ObservableCollection _selectedNodes = new ObservableCollection(); [ObservableProperty] private ConnectionViewModel? _selectedConnection; [ObservableProperty] private ObservableCollection _selectedConnections = new ObservableCollection(); public List? Stations { get; } private ProcessViewModel? _process; public ICommand DeleteSelectionCommand { get; } public static List ActionList => Enum.GetNames(typeof(RgvCommandEnum)).ToList(); // 直接获取枚举名称字符串列表 public static List StationStateList => Enum.GetNames(typeof(StationStateEnum)).ToList(); // 直接获取枚举名称字符串列表 private List actions = new List() { RgvCommandEnum.MoveFrom.ToString(), RgvCommandEnum.Pick.ToString(), RgvCommandEnum.MoveTo.ToString(), RgvCommandEnum.Place.ToString() }; private IProcessFlowService _processFlowService; public ProcessEditDialogViewModel(List? stations, ProcessViewModel? process, IProcessFlowService processFlowService) { Stations = stations; _process = process; _processFlowService = processFlowService; PendingConnection = new PendingConnectionViewModel(this); DeleteSelectionCommand = new RelayCommand(DeleteSelection, () => SelectedNodes.Count > 0 || SelectedConnections.Count > 0); GlobalData.Instance.AddOrUpdate("Stations", Stations); Nodes.WhenRemoved(x => DisconnectStation(x)) .WhenCleared(x => { Connections.Clear(); }); DispatcherTimer.RunOnce((async () => { await InitFlowDataAsync(); }), TimeSpan.FromSeconds(0), DispatcherPriority.Default); } /// /// 删除工站同时,删除与之相关的连接 /// /// public void DisconnectStation(StationNodeViewModel state) { var transitions = Connections.Where(t => t.Source.NodeId == state.Id || t.Target.NodeId == state.Id).ToList(); transitions.ForEach(t => Connections.Remove(t)); } public void Connect(ConnectorViewModel source, ConnectorViewModel target) { var conn = new ConnectionViewModel(source, target); Connections.Add(conn); } private async Task InitFlowDataAsync() { if (_process == null || string.IsNullOrWhiteSpace(_process.FlowData)) return; try { var flow = JsonConvert.DeserializeObject(_process.FlowData); if (flow != null) { Nodes.Clear(); foreach (var node in flow.Nodes) { Nodes.Add(node); } var flows = await _processFlowService.GetAllAsync(); var existingFlows = flows.Where(f => f.ProcessId == _process.Id); Connections.Clear(); foreach (var conn in flow.Connections) { // 根据 Source 和 Target 的 StationId 找到 Nodes 中对应的 ConnectorViewModel var sourceNode = Nodes.FirstOrDefault(n => n.Id == conn.Source.NodeId); var targetNode = Nodes.FirstOrDefault(n => n.Id == conn.Target.NodeId); if (sourceNode != null && targetNode != null) { // 这里假设连接都是 Output -> Input var newConn = new ConnectionViewModel(sourceNode.Output, targetNode.Input); newConn.ProcessFlow = conn.ProcessFlow; var existFlow = existingFlows.FirstOrDefault(f => f.FromStationId1 == newConn.ProcessFlow.FromStationId1 && f.ToStationId1 == newConn.ProcessFlow.ToStationId1 && f.FromStationId2 == newConn.ProcessFlow.FromStationId2 && f.ToStationId2 == newConn.ProcessFlow.ToStationId2); if (existFlow != null) { // 更新已有流程 newConn.ProcessFlow.Id = existFlow.Id; newConn.ProcessFlow.FromStatus1 = existFlow.FromStatus1; newConn.ProcessFlow.ToStatus1 = existFlow.ToStatus1; newConn.ProcessFlow.FromStatus2 = existFlow.FromStatus2; newConn.ProcessFlow.ToStatus2 = existFlow.ToStatus2; newConn.ProcessFlow.Priority = existFlow.Priority; } Connections.Add(newConn); } } } } catch (Exception ex) { // 可根据需要添加日志或通知 Debug.WriteLine($"InitFlowData 反序列化失败: {ex.Message}"); } } private void DeleteSelection() { foreach (var connection in SelectedConnections.ToList()) { connection.Source.IsConnected = false; connection.Target.IsConnected = false; Connections.Remove(connection); } var selected = SelectedNodes.ToList(); for (int i = 0; i < selected.Count; i++) { Nodes.Remove(selected[i]); } } [RelayCommand] private void AddStation(Point point) { Nodes.Add(new StationNodeViewModel { Location = point }); } public void Close() { RequestClose?.Invoke(this, false); } [RelayCommand] private void Ok() { if (_process != null) { foreach (var conn in Connections) { // 设置工艺流转的起止工站ID if (conn.ProcessFlow != null) { conn.ProcessFlow.FromStationId1 = conn.Source.NodeId == Guid.Empty ? 0 : Nodes.FirstOrDefault(n => n.Id == conn.Source.NodeId)?.Station1Id ?? 0; conn.ProcessFlow.ToStationId1 = conn.Target.NodeId == Guid.Empty ? 0 : Nodes.FirstOrDefault(n => n.Id == conn.Target.NodeId)?.Station1Id ?? 0; conn.ProcessFlow.FromStationId2 = conn.Source.NodeId == Guid.Empty ? 0 : Nodes.FirstOrDefault(n => n.Id == conn.Source.NodeId)?.Station2Id ?? 0; conn.ProcessFlow.ToStationId2 = conn.Target.NodeId == Guid.Empty ? 0 : Nodes.FirstOrDefault(n => n.Id == conn.Target.NodeId)?.Station2Id ?? 0; if (conn.ProcessFlow.FromStationId2 == 0) { conn.ProcessFlow.FromStatus2 = StationStateEnum.UnKnown.ToString(); } if (conn.ProcessFlow.ToStationId2 == 0) { conn.ProcessFlow.ToStatus2 = StationStateEnum.UnKnown.ToString(); } conn.ProcessFlow.Action = JsonConvert.SerializeObject(actions); conn.ProcessFlow.ProcessId = _process.Id; } } var flow = new FlowDataDto { Nodes = Nodes.ToList(), Connections = Connections.ToList() }; _process.FlowData = JsonConvert.SerializeObject(flow); } RequestClose?.Invoke(this, true); } [RelayCommand] private void Cancel() { RequestClose?.Invoke(this, false); } }