Ver código fonte

增加读取plc当前状态并变换相应的顶部颜色
增加界面图像双击放大
增加界面图像可选显示
修改mes交互log提示

KWD 5 meses atrás
pai
commit
c40de08a9a

+ 2 - 0
TeamAAS-VM/App.xaml.cs

@@ -36,6 +36,7 @@ using TeamAAS_VP.ViewModels.Product;
 using TeamAAS_VP.Views;
 using TeamAAS_VP.Views.Calibration;
 using TeamAAS_VP.Views.DebugMod;
+using TeamAAS_VP.Views.Home;
 using TeamAAS_VP.Views.Product;
 using TeamAAS_VP.Views.Setting;
 using TeamAAS_VP.Views.User;
@@ -207,6 +208,7 @@ namespace TeamAAS_VP
             containerRegistry.RegisterDialog<VisionStaticAccuracyAnalyzer>();
             containerRegistry.RegisterDialog<VisionDynamicAccuracyAnalyzer>();
             containerRegistry.RegisterDialog<PlcPointOffserParams>();
+            containerRegistry.RegisterDialog<ImagePreviewWindow>();
             //**************************************************************************************
 
             // 注册 SQLSugar 客户端(单例模式)

+ 110 - 4
TeamAAS-VM/Core/Management.cs

@@ -89,6 +89,14 @@ namespace TeamAAS_VP.Core
 
         #region 属性
 
+        private System.Windows.Media.Brush _StatusBackground;
+
+        public System.Windows.Media.Brush StatusBackground
+        {
+            get { return _StatusBackground; }
+            set { SetProperty(ref _StatusBackground, value); }
+        }
+
         private ObservableCollection<ShowRender> _Renders;
 
         /// <summary>
@@ -1111,7 +1119,11 @@ namespace TeamAAS_VP.Core
                 addressConfig.In_RequestPosition.Address,
                 addressConfig.In_ScrewTeachExe.Address,
                 addressConfig.In_PickINC.Address,
-                 addressConfig.In_Throw.Address,
+                addressConfig.In_Throw.Address,
+                addressConfig.RunMode.Address,
+                addressConfig.ManualMode.Address,
+                addressConfig.ClearMode.Address,
+                addressConfig.Fault.Address,
             };
             for (int i = 0; i < 10; i++)
             {
@@ -1297,7 +1309,7 @@ namespace TeamAAS_VP.Core
         string[] model_num = new string[10];//产品model_num
         string[] color = new string[10];//产品color
         string[] ppid = new string[10];//产品ppid
-        string[] revision = new string[10];//产品revision
+        string[] revision { get; set; } = new string[10];//产品revision
         /// <summary>
         /// 二次定位相机的工具坐标
         /// </summary>
@@ -1317,6 +1329,10 @@ namespace TeamAAS_VP.Core
         bool _LastFixedCameraPutExe = false;
         bool _LastFixedCameracheckExe = false;
         bool _LastThrowExe = false;
+        bool _LastRunModel = false;
+        bool _LastManualMode = false;
+        bool _LastClearMode = false;
+        bool _LastFault = false;
         Int16 _LastQrCodePhotoRequest = 0;
         Int16[] _LastWorkStart = new Int16[7];
         Int16[] _LastWorkDone = new Int16[7];
@@ -2314,6 +2330,96 @@ namespace TeamAAS_VP.Core
                         }
                     }
                 }
+                //切换成自动运行模式
+                else if (addressConfig.RunMode.Address.Contains(tuple.nodeId))
+                {
+                    if (tuple.value is bool state)
+                    {
+                        if (_LastRunModel != state)
+                        {
+                            _LastRunModel = state;
+                        }
+                        else
+                        {
+                            return;
+                        }
+                        if (state)
+                        {
+                            SendTaskMessage("收到切换成自动模式", MessageLevel.Info);
+                            StatusBackground = System.Windows.Media.Brushes.Green;
+                        }
+                    }
+                }
+                //切换成维修模式
+                else if (addressConfig.ManualMode.Address.Contains(tuple.nodeId))
+                {
+                    if (tuple.value is bool state)
+                    {
+                        if (_LastManualMode != state)
+                        {
+                            _LastManualMode = state;
+                        }
+                        else
+                        {
+                            return;
+                        }
+                        if (state)
+                        {
+                            SendTaskMessage("收到切换成维修模式", MessageLevel.Info);
+                            StatusBackground = System.Windows.Media.Brushes.Yellow;
+                        }
+                        else
+                        {
+                            SendTaskMessage("收到切换成自动模式", MessageLevel.Info);
+                            StatusBackground = System.Windows.Media.Brushes.Green;
+                        }
+                    }
+                }
+                //切换成流线模式
+                else if (addressConfig.ClearMode.Address.Contains(tuple.nodeId))
+                {
+                    if (tuple.value is bool state)
+                    {
+                        if (_LastClearMode != state)
+                        {
+                            _LastClearMode = state;
+                        }
+                        else
+                        {
+                            return;
+                        }
+                        if (state)
+                        {
+                            SendTaskMessage("收到切换成流线模式", MessageLevel.Info);
+                            StatusBackground = System.Windows.Media.Brushes.Green;
+                        }
+                    }
+                }
+                //plc报警
+                else if (addressConfig.Fault.Address.Contains(tuple.nodeId))
+                {
+                    if (tuple.value is bool state)
+                    {
+                        if (_LastFault != state)
+                        {
+                            _LastFault = state;
+                        }
+                        else
+                        {
+                            return;
+                        }
+                        if (state)
+                        {
+                            SendTaskMessage("收到PLC报警", MessageLevel.Error);
+                            StatusBackground = System.Windows.Media.Brushes.Red;
+                        }
+                        else
+                        {
+                            SendTaskMessage("收到PLC消除报警", MessageLevel.Debug);
+                            StatusBackground = System.Windows.Media.Brushes.Green;
+                        }
+                    }
+                }
                 else
                 {
                     // 过站检查
@@ -2584,7 +2690,7 @@ namespace TeamAAS_VP.Core
                                     var stationConfig = _configService.GetDeviceInfo(i);
                                     SendTaskMessage($"收到{i}:{stationConfig.DeviceName}上传本站数据请求...", MessageLevel.Debug);
                                     //从服务器中获取当前时间
-                                    var serverTimeResult = await _mesService.GetServerTimeAsync(i, code, 2);
+                                    var serverTimeResult = await _mesService.GetServerTimeAsync(i, ProductMainSN[i], 2);
 
                                     double ct = serverTimeResult.Now.Subtract(_LastMesCheckTime[i]).TotalSeconds;
                                     if (i == 0)
@@ -3001,7 +3107,7 @@ namespace TeamAAS_VP.Core
                     {
                         try
                         {
-                            float pressure = plc.ReadNode<float>(string.Format(addressConfig.In_PressureValue.Address, Index));
+                            float pressure = plc.ReadNode<float>(string.Format(addressConfig.In_CurPressureValue.Address, Index));
                             lock (_pressureSamples[Index])
                             {
                                 _pressureSamples[Index].Add((DateTime.Now, pressure));

+ 71 - 0
TeamAAS-VM/Models/PLC/PlcAddressConfig.cs

@@ -379,6 +379,8 @@ namespace TeamAAS_VP.Models.PLC
             set { SetProperty(ref _Down_WetOut_Num_max, value); }
         }
 
+
+
         #endregion
 
         #region 从PLC读取的地址
@@ -663,6 +665,50 @@ namespace TeamAAS_VP.Models.PLC
             get { return _In_Throw; }
             set { SetProperty(ref _In_Throw, value); }
         }
+
+
+        private PlcAddress _In_CurPressureValue = new PlcAddress();
+        /// <summary>
+        /// 压力值
+        /// </summary>
+        public PlcAddress In_CurPressureValue
+        {
+            get { return _In_CurPressureValue; }
+            set { SetProperty(ref _In_CurPressureValue, value); }
+        }
+
+        private PlcAddress _RunMode;
+
+        public PlcAddress RunMode
+        {
+            get { return _RunMode; }
+            set { SetProperty(ref _RunMode, value); }
+        }
+
+        private PlcAddress _ManualMode;
+
+        public PlcAddress ManualMode
+        {
+            get { return _ManualMode; }
+            set { SetProperty(ref _ManualMode, value); }
+        }
+
+        private PlcAddress _ClearMode;
+
+        public PlcAddress ClearMode
+        {
+            get { return _ClearMode; }
+            set { SetProperty(ref _ClearMode, value); }
+        }
+
+        private PlcAddress _Fault;
+
+        public PlcAddress Fault
+        {
+            get { return _Fault; }
+            set { SetProperty(ref _Fault, value); }
+        }
+
         #endregion
 
         public PlcAddressConfig()
@@ -1110,6 +1156,11 @@ namespace TeamAAS_VP.Models.PLC
             In_PressureValue.DataType = "float";
             In_PressureValue.Description = "压力值";
 
+            In_CurPressureValue = Ensure(In_CurPressureValue);
+            In_CurPressureValue.Address = "ns=4;s=DB_DriveControl|AICtrl[{0}].Status.UserData"; ;// "ns=4;s=DB_DriveControl|AICtrl[{0}].Status.UserData";
+            In_CurPressureValue.DataType = "float";
+            In_CurPressureValue.Description = "实时压力值";
+
             In_ScrewTeachExe = Ensure(In_ScrewTeachExe);
             In_ScrewTeachExe.Address = "ns=4;s=DB_Communication|ToPC.ScrewTeachExe";
             In_ScrewTeachExe.DataType = "bool";
@@ -1145,6 +1196,26 @@ namespace TeamAAS_VP.Models.PLC
             In_Throw.DataType = "Bool";
             In_Throw.Description = "抛料信号";
 
+            RunMode = Ensure(RunMode);
+            RunMode.Address = "ns=4;s=DB_Control|Mode.Status.RunMode";
+            RunMode.DataType = "Bool";
+            RunMode.Description = "自动运行模式";
+
+            ManualMode = Ensure(ManualMode);
+            ManualMode.Address = "ns=4;s=DB_Control|Mode.Status.ManualMode";
+            ManualMode.DataType = "Bool";
+            ManualMode.Description = "维修模式";
+
+            ClearMode = Ensure(ClearMode);
+            ClearMode.Address = "ns=4;s=DB_Control|Mode.Status.ClearMode";
+            ClearMode.DataType = "Bool";
+            ClearMode.Description = "流线模式";
+
+            Fault = Ensure(Fault);
+            Fault.Address = "ns=4;s=DB_Control|Mode.Status.Fault";
+            Fault.DataType = "Bool";
+            Fault.Description = "报警";
+
             // 说明:若项目中 PlcAddress 的实际属性名或类型与此不同(例如使用枚举、不同字段名),
             // 请根据实际类型调整赋值。本方法主要提供合理的默认字符串地址、数据类型及描述,便于后续从配置覆盖。
         }

+ 13 - 0
TeamAAS-VM/Models/Product/ProcedureModel.cs

@@ -234,6 +234,16 @@ namespace TeamAAS_VP.Models
             set { SetProperty(ref _IsExcludeNearPoint, value); }
         }
 
+        private bool _IsImageVisibility = true;
+        /// <summary>
+        /// 是否剔除本次识别到的物料与上一次识别到的物料位置过近的点
+        /// </summary>
+        public bool IsImageVisibility
+        {
+            get { return _IsImageVisibility; }
+            set { SetProperty(ref _IsImageVisibility, value); }
+        }
+
         private double _ExcludeNearPointThreshol = 1;
         /// <summary>
         /// 物料位置过近阈值
@@ -381,6 +391,7 @@ namespace TeamAAS_VP.Models
             FeederWorks = new FeederWorks();
             FeederStockWorks = new FeederStockWorks();
             LightChannels = new ObservableCollection<ChannelConfig>();
+            IsImageVisibility = true;
         }
 
         public ProcedureModel(string name, string cameraName, Guid cameraId)
@@ -396,6 +407,7 @@ namespace TeamAAS_VP.Models
             FeederWorks = new FeederWorks();
             FeederStockWorks = new FeederStockWorks();
             LightChannels = new ObservableCollection<ChannelConfig>();
+            IsImageVisibility = true;
         }
 
         public ProcedureModel Clone()
@@ -436,6 +448,7 @@ namespace TeamAAS_VP.Models
                 IsExcludeNearPoint = this.IsExcludeNearPoint,
                 ExcludeNearPointThreshol = this.ExcludeNearPointThreshol,
                 OutputPointMode = this.OutputPointMode,
+                IsImageVisibility = this.IsImageVisibility,
                 OutputSeparator = this.OutputSeparator,
                 UserDefineParameters = new ObservableCollection<ProcedureUserDefineParam>(this.UserDefineParameters.Select(udp => udp.Copy())),
                 LightChannels = this.LightChannels == null ? new ObservableCollection<ChannelConfig>() : new ObservableCollection<ChannelConfig>(this.LightChannels.Select(ch => new ChannelConfig

+ 8 - 8
TeamAAS-VM/Services/MesService.cs

@@ -109,8 +109,8 @@ namespace TeamAAS_VP.Services
                 url = $"{device.MesUrl}?c=QUERY_RECORD&line={device.Line}&station={device.Station}&fixtureid={device.FixtureId}&sn={sn}&p=message,sn,wo,model_num,color,ppid,stage";
             }
 
-            LogHelper.WriteLogMes($"【询问URL】{url}");
-            SendTaskMessage($"【询问URL】{url}", MessageLevel.Info);
+            LogHelper.WriteLogMes($"【MES QUERY 询问URL】{url}");
+            SendTaskMessage($"【MES QUERY 询问URL】{url}", MessageLevel.Info);
             (bool IsSuccess, string Response) result = (false, string.Empty);
 
             for (int i = 0; i < 3; i++)
@@ -120,8 +120,8 @@ namespace TeamAAS_VP.Services
                     using (var rsp = await _httpClient.GetAsync(url))
                     {
                         var text = await rsp.Content.ReadAsStringAsync();
-                        LogHelper.WriteLogMes($"【HTTP接收】{text}");
-                        SendTaskMessage($"【HTTP接收】{text}", MessageLevel.Info);
+                        LogHelper.WriteLogMes($"【HTTP接收MES QUERY 】{text}");
+                        SendTaskMessage($"【HTTP接收MES QUERY 】{text}", MessageLevel.Info);
 
                         // "SFC_OK" 代表和 MES 连接成功
                         if (text.Contains("SFC_OK"))
@@ -471,8 +471,8 @@ namespace TeamAAS_VP.Services
             string url = "";
             url = $"{device.MesUrl}?c=QUERY_RECORD&line={device.Line}&station={device.Station}&fixtureid={device.FixtureId}&sn={sn}&p=mes_server_time";
 
-            LogHelper.WriteLogMes($"【询问URL】{url}");
-            SendTaskMessage($"【询问URL】{url}", MessageLevel.Info);
+            LogHelper.WriteLogMes($"【询问MES Time】{url}");
+            SendTaskMessage($"【询问MES Time】{url}", MessageLevel.Info);
             (bool IsSuccess, DateTime Now) result = (false, DateTime.Now);
 
             for (int i = 0; i < 3; i++)
@@ -482,8 +482,8 @@ namespace TeamAAS_VP.Services
                     using (var rsp = await _httpClient.GetAsync(url))
                     {
                         var text = await rsp.Content.ReadAsStringAsync();
-                        LogHelper.WriteLogMes($"【HTTP接收】{text}");
-                        SendTaskMessage($"【HTTP接收】{text}", MessageLevel.Info);
+                        LogHelper.WriteLogMes($"【HTTP接收到MES Time】{text}");
+                        SendTaskMessage($"【HTTP接收MES Time】{text}", MessageLevel.Info);
 
                         // "SFC_OK" 代表和 MES 连接成功
                         if (text.Contains("SFC_OK"))

+ 8 - 0
TeamAAS-VM/TeamAAS-VP.csproj

@@ -558,12 +558,16 @@
     <Compile Include="ValueConverter\CountToColumnsConverter.cs" />
     <Compile Include="ValueConverter\ImageFileNameFormatConverter.cs" />
     <Compile Include="ViewModels\DebugMod\PlcRobotManualStepViewModel.cs" />
+    <Compile Include="ViewModels\Home\ImagePreviewWindowViewModel.cs" />
     <Compile Include="ViewModels\Product\ImageDisplayViewModel.cs" />
     <Compile Include="ViewModels\Product\PlcPointOffserParamsViewModel.cs" />
     <Compile Include="ViewModels\Statistics\AssemblyRecordQueryViewModel.cs" />
     <Compile Include="ViewModels\Statistics\PhotoCaptureQueryViewModel.cs" />
     <Compile Include="ViewModels\Statistics\ProductionRecordQueryViewModel.cs" />
     <Compile Include="ViewModels\User\CardLoginWindowViewModel.cs" />
+    <Compile Include="Views\Home\ImagePreviewWindow.xaml.cs">
+      <DependentUpon>ImagePreviewWindow.xaml</DependentUpon>
+    </Compile>
     <Compile Include="Views\Product\PlcPointOffserParams.xaml.cs">
       <DependentUpon>PlcPointOffserParams.xaml</DependentUpon>
     </Compile>
@@ -1141,6 +1145,10 @@
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
     </Page>
+    <Page Include="Views\Home\ImagePreviewWindow.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
     <Page Include="Views\Product\PlcPointOffserParams.xaml">
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>

+ 111 - 0
TeamAAS-VM/ViewModels/Home/ImagePreviewWindowViewModel.cs

@@ -0,0 +1,111 @@
+using Cognex.VisionPro;
+using Prism.Events;
+using Prism.Ioc;
+using Prism.Mvvm;
+using Prism.Regions;
+using Prism.Services.Dialogs;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using TeamAAS_VP.Core;
+
+namespace TeamAAS_VP.ViewModels.Home
+{
+    public class ImagePreviewWindowViewModel : BindableBase, IDialogAware
+    {
+        #region 字段
+        IRegionManager _regionManager;
+        public IEventAggregator _eventAggregator;
+        IContainerProvider _container;
+        IDialogService _dialogService;
+        #endregion
+
+        #region 属性
+
+        private Management _management;
+
+        public Management management
+        {
+            get { return _management; }
+            set { SetProperty(ref _management, value); }
+        }
+
+        #endregion
+
+        #region 命令
+        public Prism.Commands.DelegateCommand LoadedCommand { get; set; }
+        #endregion
+
+        public ImagePreviewWindowViewModel(IRegionManager regionManager, IEventAggregator ea, IContainerProvider container, IDialogService dialogService)
+        {
+            _regionManager = regionManager;
+            _eventAggregator = ea;
+            _container = container;
+            _dialogService = dialogService;
+            management = _container.Resolve<Management>();
+            LoadedCommand = new Prism.Commands.DelegateCommand(OnLoad);
+        }
+
+
+
+        private CogRecordDisplay _CogDisp;
+
+        public CogRecordDisplay CogDisp
+        {
+            get { return _CogDisp; }
+            set { SetProperty(ref _CogDisp, value); }
+        }
+
+        private Cognex.VisionPro.ICogImage _Image;
+
+        public Cognex.VisionPro.ICogImage Image
+        {
+            get { return _Image; }
+            set { SetProperty(ref _Image, value); }
+        }
+
+        private Cognex.VisionPro.CogGraphicCollection _Graphic;
+
+        public Cognex.VisionPro.CogGraphicCollection Graphic
+        {
+            get { return _Graphic; }
+            set { SetProperty(ref _Graphic, value); }
+        }
+
+        private Cognex.VisionPro.ICogRecord _Record;
+
+        public Cognex.VisionPro.ICogRecord Record
+        {
+            get { return _Record; }
+            set { SetProperty(ref _Record, value); }
+        }
+
+        public string Title { get; set; }
+
+        public event Action<IDialogResult> RequestClose;
+
+        private void OnLoad()
+        {
+            Image = CogDisp.Image;
+            Record = CogDisp.Record;
+        }
+
+        public bool CanCloseDialog()
+        {
+            return true;
+        }
+
+        public void OnDialogClosed()
+        {
+
+        }
+
+        public void OnDialogOpened(IDialogParameters parameters)
+        {
+            CogDisp = parameters.GetValue<CogRecordDisplay>("Cog");
+        }
+
+    }
+}

+ 18 - 1
TeamAAS-VM/ViewModels/Home/ShowVisionRenderViewModel.cs

@@ -1,4 +1,5 @@
-using Prism.Commands;
+using Cognex.VisionPro;
+using Prism.Commands;
 using Prism.Events;
 using Prism.Ioc;
 using Prism.Mvvm;
@@ -9,7 +10,9 @@ using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Linq;
 using TeamAAS_VP.Core;
+using TeamAAS_VP.Events;
 using TeamAAS_VP.Models;
+using TeamAAS_VP.Resources.Languages;
 
 namespace TeamAAS_VP.ViewModels.Home
 {
@@ -69,7 +72,21 @@ namespace TeamAAS_VP.ViewModels.Home
             if (_Renders == null) { return; }
             UpdateLayout?.Invoke(_Renders);
         }
+        public void ShowImage(CogRecordDisplay cogDisp)
+        {
+            IDialogParameters parameters = new DialogParameters();
+            parameters.Add("Cog", cogDisp);
+            _dialogService.ShowDialog("ImagePreviewWindow", parameters, rst =>
+            {
+                //对话框关闭之后的回调函数,可以在这解析结果。
+                //ButtonResult result1 = rst.Result;
 
+                //if (result1 == ButtonResult.OK)
+                //{
+                _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = Lang.完成, Duration = 1 });
+                //}
+            });
+        }
         private void OnLoad()
         {
             //UpDateRenderLayout();

+ 13 - 2
TeamAAS-VM/ViewModels/MainWindowViewModel.cs

@@ -56,7 +56,7 @@ namespace TeamAAS_VP.ViewModels
         ISystemDatabaseService _systemDatabaseService;
         IDatabaseInitializer _databaseInitializer;
 
-        private Management management;
+        
         private Guid CurrentTime;
         private Guid RunTime;
         private DateTime StartTime;
@@ -65,6 +65,14 @@ namespace TeamAAS_VP.ViewModels
 
         #region 属性
 
+        private Management _management;
+
+        public Management management
+        {
+            get { return _management; }
+            set { SetProperty(ref _management, value); }
+        }
+
         private string _CompanyTitle;
         public string CompanyTitle
         {
@@ -351,7 +359,10 @@ namespace TeamAAS_VP.ViewModels
                 {
                     foreach (var item2 in item1.ProcedureModels)
                     {
-                        management.Renders.Add(new ShowRender() { Id = item2.Id, ProceductName = item2.Name });
+                        if (item2.IsImageVisibility)
+                        {
+                            management.Renders.Add(new ShowRender() { Id = item2.Id, ProceductName = item2.Name });
+                        }
                     }
                 }
                 _container.Resolve<ShowVisionRenderViewModel>().Renders = management.Renders;

+ 53 - 0
TeamAAS-VM/Views/Home/ImagePreviewWindow.xaml

@@ -0,0 +1,53 @@
+<UserControl x:Class="TeamAAS_VP.Views.Home.ImagePreviewWindow"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:prism="http://prismlibrary.com/"
+             xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
+             xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
+             xmlns:wf="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
+             xmlns:vp="clr-namespace:Cognex.VisionPro;assembly=Cognex.VisionPro.Controls"
+             xmlns:lex="http://wpflocalizeextension.codeplex.com"
+             lex:LocalizeDictionary.DesignCulture="zh-CN"
+             Height="800"
+             Width="1000"
+             lex:ResxLocalizationProvider.DefaultAssembly="TeamAAS-VP"
+             lex:ResxLocalizationProvider.DefaultDictionary="Lang"
+             prism:ViewModelLocator.AutoWireViewModel="True"
+             FontFamily="{DynamicResource DefaultFont}">
+    <b:Interaction.Triggers>
+        <b:EventTrigger EventName="Loaded">
+            <b:InvokeCommandAction Command="{Binding LoadedCommand}" />
+        </b:EventTrigger>
+    </b:Interaction.Triggers>
+
+    <prism:Dialog.WindowStyle>
+        <Style TargetType="Window">
+            <Setter Property="prism:Dialog.WindowStartupLocation"
+                Value="CenterScreen" />
+            <Setter Property="WindowStyle"
+                Value="SingleBorderWindow" />
+            <Setter Property="ResizeMode"
+                Value="NoResize" />
+            <Setter Property="SizeToContent"
+                Value="Manual" />
+            <Setter Property="AllowDrop"
+                Value="True" />
+            <Setter Property="BorderThickness"
+                Value="0" />
+            <Setter Property="ShowInTaskbar"
+                Value="True" />
+            <Setter Property="SizeToContent"
+                Value="WidthAndHeight" />
+            <Setter Property="WindowState"
+                Value="Normal" />
+            <Setter Property="Topmost"
+                Value="True" />
+        </Style>
+    </prism:Dialog.WindowStyle>
+
+    <Grid x:Name="gridRender">
+        <wf:WindowsFormsHost>
+            <vp:CogRecordDisplay x:Name="display"/>
+        </wf:WindowsFormsHost>
+    </Grid>
+</UserControl>

+ 51 - 0
TeamAAS-VM/Views/Home/ImagePreviewWindow.xaml.cs

@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using TeamAAS_VP.ViewModels.Home;
+
+namespace TeamAAS_VP.Views.Home
+{
+    /// <summary>
+    /// ImagePreviewWindow.xaml 的交互逻辑
+    /// </summary>
+    public partial class ImagePreviewWindow : UserControl
+    {
+        private ImagePreviewWindowViewModel viewModel;
+        public ImagePreviewWindow()
+        {
+            InitializeComponent();
+            viewModel = this.DataContext as ImagePreviewWindowViewModel;
+            viewModel.PropertyChanged += ViewModel_PropertyChanged;
+            display.HorizontalScrollBar = false;
+            display.VerticalScrollBar = false;
+            display.AutoFit = true;
+            display.AutoFitWithGraphics = true;
+            display.BackColor = System.Drawing.SystemColors.ActiveCaption;
+        }
+
+        private void ViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
+        {
+
+            if (e.PropertyName == "Image")
+            {
+                this.display.Image = viewModel.Image;
+            }
+            if (e.PropertyName == "Record")
+            {
+                this.display.Record = viewModel.Record;
+            }
+
+        }
+    }
+}

+ 12 - 14
TeamAAS-VM/Views/Home/ShowVisionRender.xaml.cs

@@ -175,17 +175,17 @@ namespace TeamAAS_VP.Views.Home
                     {
                         ConfigureCogDisplay(disp); // 句柄创建后再配置,最稳
                         // 绑定 WinForms 双击事件
-                        //disp.MouseDoubleClick += (r, w) =>
-                        //{
-                        //    try
-                        //    {
-                        //        OnDisplayDoubleClick(disp);
-                        //    }
-                        //    catch (Exception ex)
-                        //    {
-                        //        LogHelper.WriteLogError("双击预览弹窗出错", ex);
-                        //    }
-                        //};
+                        disp.DoubleClick += (r, w) =>
+                        {
+                            try
+                            {
+                                OnDisplayDoubleClick(disp);
+                            }
+                            catch (Exception ex)
+                            {
+                                LogHelper.WriteLogError("双击预览弹窗出错", ex);
+                            }
+                        };
                     }
                     catch (Exception ex)
                     {
@@ -702,9 +702,7 @@ namespace TeamAAS_VP.Views.Home
                     // 回到 WPF UI 线程弹窗
                     this.Dispatcher.BeginInvoke(new Action(() =>
                     {
-                        //var win = new ImagePreviewWindow(bmp, $"预览:{disp.Tag ?? "Display"}");
-                        //win.Owner = Window.GetWindow(this); // 让弹窗归属当前窗口
-                        //win.Show();
+                        viewModel.ShowImage(disp);
                     }));
                 }
                 catch (Exception ex)

+ 1 - 0
TeamAAS-VM/Views/MainWindowView.xaml

@@ -116,6 +116,7 @@
                 </Button>
                 <materialDesign:Card Grid.Column="4"
                                      Margin="10"
+                                     Background="{Binding management.StatusBackground}"
                                      UniformCornerRadius="15">
                     <TextBlock Text="{Binding MyTitle}"
                                FontSize="{DynamicResource Font.Size.Title1}"

+ 37 - 30
TeamAAS-VM/Views/Product/ProcedureParams.xaml

@@ -308,11 +308,18 @@
                               Grid.Column="1"
                               Margin="0,2,0,0"
                               IsChecked="{Binding SelectProcedure.IsExcludeNearPoint,Mode=TwoWay}" />
-                    <!--点位输出的模式-->
                     <TextBlock Grid.Row="4"
+                               Grid.Column="0"
+                               Text="是否启用当前流程图像显示" />
+                    <CheckBox Grid.Row="4"
+                              Grid.Column="1"
+                              Margin="0,2,0,0"
+                              IsChecked="{Binding SelectProcedure.IsImageVisibility,Mode=TwoWay}" />
+                    <!--点位输出的模式-->
+                    <TextBlock Grid.Row="5"
                                Grid.Column="0"
                                Text="{lex:Loc 点位输出的模式,Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0}: '}" />
-                    <ComboBox Grid.Row="4"
+                    <ComboBox Grid.Row="5"
                               Grid.Column="1"
                               SelectedItem="{Binding SelectProcedure.OutputPointMode,Mode=TwoWay}"
                               ItemsSource="{ext:EnumBindingSource EnumType=enums:OutputPointMode}"
@@ -320,10 +327,10 @@
                               BorderThickness="1"
                               Margin="0,2,0,0" />
                     <!--视觉引导模式(先拍再振/先振再拍)-->
-                    <TextBlock Grid.Row="5"
+                    <TextBlock Grid.Row="6"
                                Grid.Column="0"
                                Text="{lex:Loc 视觉引导模式,Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0}: '}" />
-                    <ComboBox Grid.Row="5"
+                    <ComboBox Grid.Row="6"
                               Grid.Column="1"
                               SelectedItem="{Binding SelectProcedure.VibrationModel,Mode=TwoWay}"
                               ItemsSource="{ext:EnumBindingSource EnumType=enums:VibrationModel}"
@@ -331,30 +338,30 @@
                               BorderThickness="1"
                               Margin="0,2,0,0" />
                     <!--拍照失败Feeder振动最大次数-->
-                    <TextBlock Grid.Row="6"
+                    <TextBlock Grid.Row="7"
                                Grid.Column="0"
                                Text="{lex:Loc Feeder最大振动拍照次数,Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0}: '}" />
-                    <mah:NumericUpDown Grid.Row="6"
+                    <mah:NumericUpDown Grid.Row="7"
                                        Grid.Column="1"
                                        Maximum="100"
                                        Minimum="1"
                                        StringFormat="{}{0:N0}"
                                        Value="{Binding SelectProcedure.FeederFailLimit,Mode=TwoWay}" />
                     <!--每次发送给机器人的点数最大值-->
-                    <TextBlock Grid.Row="7"
+                    <TextBlock Grid.Row="8"
                                Grid.Column="0"
                                Text="{lex:Loc 发送给机器人的最大点位数量,Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0}: '}" />
-                    <mah:NumericUpDown Grid.Row="7"
+                    <mah:NumericUpDown Grid.Row="8"
                                        Grid.Column="1"
                                        Maximum="100"
                                        Minimum="1"
                                        StringFormat="{}{0:N0}"
                                        Value="{Binding SelectProcedure.OutputPointCountMax,Mode=TwoWay}" />
                     <!--视觉流程输出项之间的分割符-->
-                    <TextBlock Grid.Row="8"
+                    <TextBlock Grid.Row="9"
                                Grid.Column="0"
                                Text="{lex:Loc 视觉流程输出项之间的分割符,Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0}: '}" />
-                    <TextBox Grid.Row="8"
+                    <TextBox Grid.Row="9"
                              Grid.Column="1"
                              Text="{Binding SelectProcedure.OutputSeparator,Mode=TwoWay}"
                              BorderThickness="1"
@@ -362,44 +369,44 @@
                              HorizontalAlignment="Stretch"
                              Margin="0,2,0,0" />
                     <!--保存图像-->
-                    <TextBlock Grid.Row="9"
+                    <TextBlock Grid.Row="10"
                                Grid.Column="0"
                                Text="{lex:Loc 保存图像,Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0}: '}" />
                     <CheckBox x:Name="chbSaveImage"
-                              Grid.Row="9"
+                              Grid.Row="10"
                               Grid.Column="1"
                               d:IsChecked="True"
                               Content="{lex:Loc 是否保存,Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0}: '}"
                               IsChecked="{Binding SelectProcedure.IsSaveImage,Mode=TwoWay}"
                               Style="{StaticResource MaterialDesignLightCheckBox}" />
                     <!--保存图像模式-->
-                    <TextBlock Grid.Row="10"
+                    <TextBlock Grid.Row="11"
                                Grid.Column="0"
                                Visibility="{Binding ElementName=chbSaveImage,Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}"
                                Text="{lex:Loc 图像存储模式,Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0}: '}" />
-                    <ComboBox Grid.Row="10"
+                    <ComboBox Grid.Row="11"
                               Grid.Column="1"
                               Visibility="{Binding ElementName=chbSaveImage,Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}"
                               materialDesign:HintAssist.Hint="{lex:Loc 图像存储模式}"
                               SelectedItem="{Binding SelectProcedure.SaveImageModel,Mode=TwoWay}"
                               ItemsSource="{ext:EnumBindingSource EnumType=enums:ProcedureSaveImageModel}" />
                     <!--保存图像路径存放模式-->
-                    <TextBlock Grid.Row="11"
+                    <TextBlock Grid.Row="12"
                                Grid.Column="0"
                                Visibility="{Binding ElementName=chbSaveImage,Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}"
                                Text="{lex:Loc 图像路径存储方式,Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0}: '}" />
-                    <ComboBox Grid.Row="11"
+                    <ComboBox Grid.Row="12"
                               Grid.Column="1"
                               Visibility="{Binding ElementName=chbSaveImage,Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}"
                               materialDesign:HintAssist.Hint="{lex:Loc 图像路径存储方式}"
                               SelectedItem="{Binding SelectProcedure.SaveImagePathModel,Mode=TwoWay}"
                               ItemsSource="{ext:EnumBindingSource EnumType=enums:ProcedureSaveImagePathModel}" />
                     <!--保存路径-->
-                    <TextBlock Grid.Row="12"
+                    <TextBlock Grid.Row="13"
                                Grid.Column="0"
                                Visibility="{Binding ElementName=chbSaveImage,Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}"
                                Text="{lex:Loc 保存路径,Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0}: '}" />
-                    <Grid Grid.Row="12"
+                    <Grid Grid.Row="13"
                           Grid.Column="1"
                           Visibility="{Binding ElementName=chbSaveImage,Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}">
                         <Grid.ColumnDefinitions>
@@ -421,40 +428,40 @@
                         </Button>
                     </Grid>
                     <!--是否压缩图像-->
-                    <TextBlock Grid.Row="13"
+                    <TextBlock Grid.Row="14"
                                Grid.Column="0"
                                Visibility="{Binding ElementName=chbSaveImage,Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}"
                                Text="{lex:Loc 压缩图像,Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0}: '}" />
-                    <CheckBox Grid.Row="13"
+                    <CheckBox Grid.Row="14"
                               Grid.Column="1"
                               Content="{lex:Loc 是否压缩}"
                               Visibility="{Binding ElementName=chbSaveImage,Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}"
                               IsChecked="{Binding SelectProcedure.IsCompress,Mode=TwoWay}"
                               Style="{StaticResource MaterialDesignLightCheckBox}" />
                     <!--是否延迟保存图片-->
-                    <TextBlock Grid.Row="14"
+                    <TextBlock Grid.Row="15"
                                Grid.Column="0"
                                Visibility="{Binding ElementName=chbSaveImage,Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}"
                                Text="{lex:Loc 延迟保存图片,Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0}: '}" />
-                    <CheckBox Grid.Row="14"
+                    <CheckBox Grid.Row="15"
                               Grid.Column="1"
                               Content="{lex:Loc 是否延迟保存图片}"
                               Visibility="{Binding ElementName=chbSaveImage,Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}"
                               IsChecked="{Binding SelectProcedure.IsDelaySaveImage,Mode=TwoWay}"
                               Style="{StaticResource MaterialDesignLightCheckBox}" />
                     <!--图片名称格式-->
-                    <TextBlock Grid.Row="15"
+                    <TextBlock Grid.Row="16"
                                Grid.Column="0"
                                Visibility="{Binding ElementName=chbSaveImage,Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}"
-                               Text="图片名称格式:" />
-                    <TextBox Grid.Row="15"
+                               Text="{lex:Loc 图片名称格式}" />
+                    <TextBox Grid.Row="16"
                              Grid.Column="1"
                              HorizontalAlignment="Stretch"
                              Visibility="{Binding ElementName=chbSaveImage,Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}"
                              Text="{Binding SelectProcedure.ImageFileNameFormat,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
                     </TextBox>
                     <!--示例-->
-                    <StackPanel Grid.Row="16"
+                    <StackPanel Grid.Row="17"
                                 Grid.Column="0"
                                 Grid.ColumnSpan="2"
                                 Orientation="Vertical"
@@ -465,7 +472,7 @@
                                    TextTrimming="CharacterEllipsis"
                                    TextWrapping="Wrap"
                                    Width="{Binding Width, ElementName=grid}" />
-                        <TextBlock Text="转换后的名称:"
+                        <TextBlock Text="{lex:Loc 转换后的名称}"
                                    Foreground="Gray"
                                    FontSize="10" />
                         <TextBlock Text="{Binding SelectProcedure.ImageFileNameFormat,Converter={StaticResource ImageFileNameFormatConverter},Mode=TwoWay}"
@@ -477,7 +484,7 @@
                     </StackPanel>
 
                     <!--自定义参数-->
-                    <GroupBox Grid.Row="17"
+                    <GroupBox Grid.Row="18"
                               Grid.Column="0"
                               Grid.ColumnSpan="2"
                               HorizontalAlignment="Stretch"
@@ -547,10 +554,10 @@
                             </DataGrid>
                         </DockPanel>
                     </GroupBox>
-                    <TextBlock Grid.Row="18"
+                    <TextBlock Grid.Row="19"
                                Grid.Column="0"
                                Text="{lex:Loc 重写视觉处理逻辑}" />
-                    <Button Grid.Row="18"
+                    <Button Grid.Row="19"
                             Grid.Column="1"
                             Margin="0,2,0,0"
                             Command="{Binding OverrideVisionTaskCommand}">