using AuroraDesk.Core.Entities; using AuroraDesk.Core.Interfaces; using AuroraDesk.Presentation.ViewModels.Base; using ReactiveUI; using System; using System.Collections.ObjectModel; using System.Reactive; using System.Reactive.Linq; using Microsoft.Extensions.Logging; namespace AuroraDesk.Presentation.ViewModels.Pages; /// /// 节点画布页面 ViewModel /// public class NodeCanvasPageViewModel : RoutableViewModel { private readonly INodeCanvasService _nodeCanvasService; private readonly ILogger? _logger; private Node? _selectedNode; private ConnectionPoint? _connectingSourcePoint; private bool _isConnecting; private double _canvasOffsetX; private double _canvasOffsetY; private double _canvasZoom = 1.0; public ObservableCollection Nodes => _nodeCanvasService.Nodes; public ObservableCollection Connections => _nodeCanvasService.Connections; private ObservableCollection _nodeTemplates = new(); public ObservableCollection NodeTemplates { get => _nodeTemplates; set => this.RaiseAndSetIfChanged(ref _nodeTemplates, value); } /// /// 选中的节点 /// public Node? SelectedNode { get => _selectedNode; set => this.RaiseAndSetIfChanged(ref _selectedNode, value); } /// /// 正在连接的源连接点 /// public ConnectionPoint? ConnectingSourcePoint { get => _connectingSourcePoint; set => this.RaiseAndSetIfChanged(ref _connectingSourcePoint, value); } /// /// 是否正在连接模式 /// public bool IsConnecting { get => _isConnecting; set => this.RaiseAndSetIfChanged(ref _isConnecting, value); } /// /// 画布偏移X /// public double CanvasOffsetX { get => _canvasOffsetX; set => this.RaiseAndSetIfChanged(ref _canvasOffsetX, value); } /// /// 画布偏移Y /// public double CanvasOffsetY { get => _canvasOffsetY; set => this.RaiseAndSetIfChanged(ref _canvasOffsetY, value); } /// /// 画布缩放 /// public double CanvasZoom { get => _canvasZoom; set => this.RaiseAndSetIfChanged(ref _canvasZoom, value); } // 命令 public ReactiveCommand ClearCanvasCommand { get; } public ReactiveCommand DeleteNodeCommand { get; } public ReactiveCommand StartConnectionCommand { get; } public ReactiveCommand CompleteConnectionCommand { get; } public ReactiveCommand DeleteConnectionCommand { get; } public ReactiveCommand<(double x, double y), Unit> AddNodeCommand { get; } public ReactiveCommand<(NodeTemplate template, double x, double y), Unit> AddNodeFromTemplateCommand { get; } public NodeCanvasPageViewModel( IScreen screen, INodeCanvasService nodeCanvasService, ILogger? logger = null) : base(screen, "node-canvas") { _nodeCanvasService = nodeCanvasService; _logger = logger; // 初始化节点模板 InitializeNodeTemplates(); // 初始化命令 ClearCanvasCommand = ReactiveCommand.Create(ClearCanvas); DeleteNodeCommand = ReactiveCommand.Create(DeleteNode); StartConnectionCommand = ReactiveCommand.Create(StartConnection); CompleteConnectionCommand = ReactiveCommand.Create(CompleteConnection); DeleteConnectionCommand = ReactiveCommand.Create(DeleteConnection); AddNodeCommand = ReactiveCommand.Create<(double x, double y)>(AddNode); AddNodeFromTemplateCommand = ReactiveCommand.Create<(NodeTemplate template, double x, double y)>(AddNodeFromTemplate); // 监听选中节点变化 this.WhenAnyValue(x => x.SelectedNode) .Subscribe(node => { // 取消其他节点的选中状态 foreach (var n in Nodes) { n.IsSelected = n == node; } }); _logger?.LogInformation("NodeCanvasPageViewModel 已创建"); } /// /// 初始化节点模板 /// private void InitializeNodeTemplates() { NodeTemplates.Add(new NodeTemplate { Name = "power-splitter", DisplayName = "功分器", Description = "3功分器", Content = "3功分42", InputCount = 1, OutputCount = 3, Width = 120, Height = 80 }); NodeTemplates.Add(new NodeTemplate { Name = "basic-node", DisplayName = "基础节点", Description = "基础节点模板", Content = "节点", InputCount = 1, OutputCount = 1, Width = 100, Height = 60 }); } /// /// 添加节点到画布 /// private void AddNode((double x, double y) position) { // 确保位置在合理范围内(至少为正数) var x = Math.Max(0, position.x); var y = Math.Max(0, position.y); var node = new Node { X = x, Y = y, Title = $"节点 {Nodes.Count + 1}", Content = "3功分42", Width = 120, Height = 80 }; // 添加连接点(右侧输出点) for (int i = 0; i < 3; i++) { node.ConnectionPoints.Add(new ConnectionPoint { Label = (i + 1).ToString(), Type = ConnectionPointType.Output, Index = i, Node = node }); } // 添加连接点(左侧输入点) node.ConnectionPoints.Add(new ConnectionPoint { Label = "", Type = ConnectionPointType.Input, Index = 0, Node = node }); _nodeCanvasService.AddNode(node); SelectedNode = node; _logger?.LogDebug("添加节点: {NodeId} 在位置 ({X}, {Y})", node.Id, position.x, position.y); } /// /// 删除节点 /// private void DeleteNode(Node node) { if (node == null) return; _nodeCanvasService.RemoveNode(node); if (SelectedNode == node) { SelectedNode = null; } _logger?.LogDebug("删除节点: {NodeId}", node.Id); } /// /// 开始连接 /// private void StartConnection(ConnectionPoint connectionPoint) { if (connectionPoint == null || connectionPoint.Type != ConnectionPointType.Output) return; ConnectingSourcePoint = connectionPoint; IsConnecting = true; _logger?.LogDebug("开始连接,源连接点: {PointId}", connectionPoint.Id); } /// /// 完成连接 /// private void CompleteConnection(ConnectionPoint targetPoint) { if (targetPoint == null || ConnectingSourcePoint == null) { CancelConnection(); return; } if (targetPoint.Type != ConnectionPointType.Input) { CancelConnection(); return; } var success = _nodeCanvasService.CreateConnection(ConnectingSourcePoint, targetPoint); if (success) { _logger?.LogDebug("连接成功: {SourceId} -> {TargetId}", ConnectingSourcePoint.Id, targetPoint.Id); } else { _logger?.LogWarning("连接失败: {SourceId} -> {TargetId}", ConnectingSourcePoint.Id, targetPoint.Id); } CancelConnection(); } /// /// 取消连接 /// public void CancelConnection() { ConnectingSourcePoint = null; IsConnecting = false; } /// /// 删除连接 /// private void DeleteConnection(Connection connection) { if (connection == null) return; _nodeCanvasService.RemoveConnection(connection); _logger?.LogDebug("删除连接: {ConnectionId}", connection.Id); } /// /// 清空画布 /// private void ClearCanvas() { _nodeCanvasService.Clear(); SelectedNode = null; _logger?.LogDebug("清空画布"); } /// /// 更新节点位置 /// public void UpdateNodePosition(Node node, double x, double y) { _nodeCanvasService.UpdateNodePosition(node, x, y); } /// /// 从模板添加节点到画布 /// private void AddNodeFromTemplate((NodeTemplate template, double x, double y) args) { var node = args.template.CreateNode(args.x, args.y); _nodeCanvasService.AddNode(node); SelectedNode = node; _logger?.LogDebug("从模板添加节点: {TemplateName} 在位置 ({X}, {Y})", args.template.Name, args.x, args.y); } }