using Prism.Commands; using Prism.Events; using Prism.Ioc; using Prism.Mvvm; using Microsoft.Win32; using System; using System.Collections.ObjectModel; using System.Configuration; using System.IO; using System.Windows; using System.Windows.Media.Imaging; using XplorePlane.Events; using XP.Common.Logging.Interfaces; using XP.Common.PdfViewer.Interfaces; using XP.Hardware.MotionControl.Abstractions; namespace XplorePlane.ViewModels { public class MainViewModel : BindableBase { private readonly ILoggerService _logger; private readonly IContainerProvider _containerProvider; private readonly IEventAggregator _eventAggregator; private string _licenseInfo = "当前时间"; public string LicenseInfo { get => _licenseInfo; set => SetProperty(ref _licenseInfo, value); } public ObservableCollection NavigationTree { get; set; } // 导航命令 public DelegateCommand NavigateHomeCommand { get; set; } public DelegateCommand NavigateInspectCommand { get; set; } public DelegateCommand OpenFileCommand { get; set; } public DelegateCommand ExportCommand { get; set; } public DelegateCommand ClearCommand { get; set; } public DelegateCommand EditPropertiesCommand { get; set; } // 窗口打开命令 public DelegateCommand OpenImageProcessingCommand { get; } public DelegateCommand LoadImageCommand { get; } public DelegateCommand OpenPipelineEditorCommand { get; } public DelegateCommand OpenCncEditorCommand { get; } public DelegateCommand OpenMatrixEditorCommand { get; } public DelegateCommand OpenToolboxCommand { get; } public DelegateCommand OpenLibraryVersionsCommand { get; } public DelegateCommand OpenUserManualCommand { get; } public DelegateCommand OpenCameraSettingsCommand { get; } // 硬件命令 public DelegateCommand AxisResetCommand { get; } public DelegateCommand OpenDetectorConfigCommand { get; } public DelegateCommand OpenMotionDebugCommand { get; } public DelegateCommand OpenPlcAddrConfigCommand { get; } public DelegateCommand OpenRaySourceConfigCommand { get; } public DelegateCommand WarmUpCommand { get; } // 设置命令 public DelegateCommand OpenLanguageSwitcherCommand { get; } public DelegateCommand OpenRealTimeLogViewerCommand { get; } // 窗口引用(单例窗口防止重复打开) private Window _motionDebugWindow; private Window _detectorConfigWindow; private Window _plcAddrConfigWindow; private Window _realTimeLogViewerWindow; private Window _toolboxWindow; private Window _raySourceConfigWindow; public MainViewModel(ILoggerService logger, IContainerProvider containerProvider, IEventAggregator eventAggregator) { _logger = logger?.ForModule() ?? throw new ArgumentNullException(nameof(logger)); _containerProvider = containerProvider ?? throw new ArgumentNullException(nameof(containerProvider)); _eventAggregator = eventAggregator ?? throw new ArgumentNullException(nameof(eventAggregator)); NavigationTree = new ObservableCollection(); // 导航命令 NavigateHomeCommand = new DelegateCommand(OnNavigateHome); NavigateInspectCommand = new DelegateCommand(OnNavigateInspect); OpenFileCommand = new DelegateCommand(OnOpenFile); ExportCommand = new DelegateCommand(OnExport); ClearCommand = new DelegateCommand(OnClear); EditPropertiesCommand = new DelegateCommand(OnEditProperties); // 窗口打开命令 OpenImageProcessingCommand = new DelegateCommand(() => ShowWindow(new Views.ImageProcessingWindow(), "图像处理")); LoadImageCommand = new DelegateCommand(ExecuteLoadImage); OpenPipelineEditorCommand = new DelegateCommand(() => ShowWindow(new Views.PipelineEditorWindow(), "流水线编辑器")); OpenCncEditorCommand = new DelegateCommand(() => ShowWindow(new Views.Cnc.CncEditorWindow(), "CNC 编辑器")); OpenMatrixEditorCommand = new DelegateCommand(() => ShowWindow(new Views.Cnc.MatrixEditorWindow(), "矩阵编排")); OpenToolboxCommand = new DelegateCommand(ExecuteOpenToolbox); OpenLibraryVersionsCommand = new DelegateCommand(() => ShowWindow(new Views.LibraryVersionsWindow(), "关于")); OpenUserManualCommand = new DelegateCommand(ExecuteOpenUserManual); OpenCameraSettingsCommand = new DelegateCommand(ExecuteOpenCameraSettings); // 硬件命令 AxisResetCommand = new DelegateCommand(ExecuteAxisReset); OpenDetectorConfigCommand = new DelegateCommand(ExecuteOpenDetectorConfig); OpenMotionDebugCommand = new DelegateCommand(ExecuteOpenMotionDebug); OpenPlcAddrConfigCommand = new DelegateCommand(ExecuteOpenPlcAddrConfig); OpenRaySourceConfigCommand = new DelegateCommand(ExecuteOpenRaySourceConfig); WarmUpCommand = new DelegateCommand(ExecuteWarmUp); // 设置命令 OpenLanguageSwitcherCommand = new DelegateCommand(ExecuteOpenLanguageSwitcher); OpenRealTimeLogViewerCommand = new DelegateCommand(ExecuteOpenRealTimeLogViewer); _logger.Info("MainViewModel 已初始化"); } #region 通用窗口辅助方法 /// /// 显示一个新窗口(非模态) /// private void ShowWindow(Window window, string name) { window.Owner = Application.Current.MainWindow; window.Show(); _logger.Info("{Name} 窗口已打开", name); } /// /// 显示或激活单例窗口(非模态,防止重复打开) /// private void ShowOrActivate(Window currentWindow, Action setWindow, Func factory, string name) { if (currentWindow != null && currentWindow.IsLoaded) { currentWindow.Activate(); return; } var window = factory(); window.Owner = Application.Current.MainWindow; window.ShowInTaskbar = true; window.Closed += (s, e) => setWindow(null); window.Show(); setWindow(window); _logger.Info("{Name} 窗口已打开", name); } #endregion #region 窗口打开命令实现 private void ExecuteOpenToolbox() { ShowOrActivate(_toolboxWindow, w => _toolboxWindow = w, () => new Views.OperatorToolboxWindow(), "算子工具箱"); } private void ExecuteOpenUserManual() { try { var manualPath = ConfigurationManager.AppSettings["UserManual"]; if (string.IsNullOrEmpty(manualPath)) { _logger.Warn("未配置用户手册路径"); MessageBox.Show("未配置用户手册路径,请检查 App.config 中的 UserManual 配置项。", "提示", MessageBoxButton.OK, MessageBoxImage.Warning); return; } if (!File.Exists(manualPath)) { _logger.Warn("用户手册文件不存在:{Path}", manualPath); MessageBox.Show($"用户手册文件不存在:\n{manualPath}", "提示", MessageBoxButton.OK, MessageBoxImage.Warning); return; } var pdfViewerService = _containerProvider.Resolve(); var stream = File.OpenRead(manualPath); var fileName = Path.GetFileName(manualPath); pdfViewerService.OpenViewer(stream, fileName); } catch (Exception ex) { _logger.Error(ex, "打开用户手册失败"); MessageBox.Show($"打开用户手册失败:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); } } private void ExecuteOpenCameraSettings() { try { var vm = _containerProvider.Resolve(); if (!vm.IsCameraConnected) { MessageBox.Show("请先连接相机", "提示", MessageBoxButton.OK, MessageBoxImage.Information); return; } var window = new Views.CameraSettingsWindow(vm) { Owner = Application.Current.MainWindow }; window.Show(); } catch (Exception ex) { _logger.Error(ex, "打开相机设置失败"); } } #endregion #region 硬件命令实现 private void ExecuteAxisReset() { var result = MessageBox.Show("确认执行轴复位操作?", "轴复位", MessageBoxButton.OKCancel, MessageBoxImage.Question); if (result != MessageBoxResult.OK) return; try { var motionSystem = _containerProvider.Resolve(); var resetResult = motionSystem.AxisReset.Reset(); if (!resetResult.Success) { MessageBox.Show($"轴复位失败:{resetResult.ErrorMessage}", "错误", MessageBoxButton.OK, MessageBoxImage.Warning); } } catch (Exception ex) { _logger.Error(ex, "轴复位异常"); MessageBox.Show($"轴复位异常:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); } } private void ExecuteOpenDetectorConfig() { try { ShowOrActivate(_detectorConfigWindow, w => _detectorConfigWindow = w, () => new XP.Hardware.Detector.Views.DetectorConfigWindow(), "探测器配置"); } catch (Exception ex) { _logger.Error(ex, "打开探测器配置窗口失败"); MessageBox.Show($"打开探测器配置窗口失败:\n{ex.InnerException?.Message ?? ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); } } private void ExecuteOpenMotionDebug() { ShowOrActivate(_motionDebugWindow, w => _motionDebugWindow = w, () => new XP.Hardware.MotionControl.Views.MotionDebugWindow(), "运动调试"); } private void ExecuteOpenPlcAddrConfig() { ShowOrActivate(_plcAddrConfigWindow, w => _plcAddrConfigWindow = w, () => _containerProvider.Resolve(), "PLC 地址配置"); } private void ExecuteOpenRaySourceConfig() { ShowOrActivate(_raySourceConfigWindow, w => _raySourceConfigWindow = w, () => new XP.Hardware.RaySource.Views.RaySourceConfigWindow(), "射线源配置"); } private void ExecuteLoadImage() { var dialog = new OpenFileDialog { Title = "加载图像", Filter = "图像文件|*.bmp;*.png;*.jpg;*.jpeg;*.tif;*.tiff|所有文件|*.*" }; if (dialog.ShowDialog() != true) return; try { var bitmap = new BitmapImage(); bitmap.BeginInit(); bitmap.UriSource = new Uri(dialog.FileName, UriKind.Absolute); bitmap.CacheOption = BitmapCacheOption.OnLoad; bitmap.EndInit(); bitmap.Freeze(); _eventAggregator.GetEvent() .Publish(new ManualImageLoadedPayload(bitmap, dialog.FileName)); } catch (Exception ex) { _logger.Error(ex, "加载图像失败:{Path}", dialog.FileName); MessageBox.Show($"加载图像失败:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); } } private void ExecuteWarmUp() { var messageBoxResult = MessageBox.Show("确认执行射线源暖机操作?", "暖机", MessageBoxButton.OKCancel, MessageBoxImage.Question); if (messageBoxResult != MessageBoxResult.OK) return; try { var raySourceService = _containerProvider.Resolve(); var result = raySourceService.WarmUp(); if (!result.Success) { MessageBox.Show($"暖机失败:{result.ErrorMessage}", "错误", MessageBoxButton.OK, MessageBoxImage.Warning); } else { _logger.Info("暖机命令已发送"); } } catch (Exception ex) { _logger.Error(ex, "暖机异常"); MessageBox.Show($"暖机异常:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); } } #endregion #region 设置命令实现 private void ExecuteOpenLanguageSwitcher() { try { var viewModel = _containerProvider.Resolve(); var window = new XP.Common.Localization.Views.LanguageSwitcherWindow(viewModel) { Owner = Application.Current.MainWindow, ShowInTaskbar = true }; window.ShowDialog(); } catch (Exception ex) { _logger.Error(ex, "打开语言设置失败"); } } private void ExecuteOpenRealTimeLogViewer() { ShowOrActivate(_realTimeLogViewerWindow, w => _realTimeLogViewerWindow = w, () => new XP.Common.GeneralForm.Views.RealTimeLogViewer(), "实时日志"); } #endregion #region 导航命令实现 private void OnNavigateHome() { _logger.Info("导航到主页"); LicenseInfo = "主页"; } private void OnNavigateInspect() { _logger.Info("导航到检测页面"); LicenseInfo = "检测页面"; } private void OnOpenFile() { _logger.Info("打开文件"); LicenseInfo = "打开文件"; } private void OnExport() { _logger.Info("导出数据"); LicenseInfo = "导出数据"; } private void OnClear() { _logger.Info("清除数据"); LicenseInfo = "清除数据"; } private void OnEditProperties() { _logger.Info("编辑属性"); LicenseInfo = "编辑属性"; } #endregion } }