Преглед изворни кода

批量设置点位补偿值功能及视觉流程优化

新增点位补偿参数批量设置弹窗,PlcPoint模型扩展补偿属性,支持批量清零和编辑。点位参数界面优化,导入CAD点位时可清零补偿值。锁附拍照点位支持视觉流程选择,流程名称自动同步。修复部分细节,完善异常处理,项目文件已添加相关引用。
孝锋 徐 пре 8 месеци
родитељ
комит
2fb359f3f0

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

@@ -212,6 +212,7 @@ namespace TeamAAS_VP
             containerRegistry.RegisterDialog<AddScrew>();
             containerRegistry.RegisterDialog<ChangeHeader>();
             containerRegistry.RegisterDialog<ChangeNozzle>();
+            containerRegistry.RegisterDialog<PlcPointOffserParams>();
             //**************************************************************************************
 
             // 注册 SQLSugar 客户端(单例模式)

+ 40 - 25
TeamAAS-VM/Core/Management.cs

@@ -213,7 +213,7 @@ namespace TeamAAS_VP.Core
 
         public Management(IRegionManager regionManager, IEventAggregator ea, IContainerProvider container, IConfigService configService,
             IRobotService robotService, ICameraService cameraService, IFeederService feederService, IPlcService plcService, IProductService productService,
-            ICalibrationService calibrationService, IRemoteCommandService remoteCommandService, ISystemDatabaseService systemDatabaseService, ILightManagerService lightManagerService, 
+            ICalibrationService calibrationService, IRemoteCommandService remoteCommandService, ISystemDatabaseService systemDatabaseService, ILightManagerService lightManagerService,
             IMesService mesService)
         {
             _regionManager = regionManager;
@@ -248,17 +248,17 @@ namespace TeamAAS_VP.Core
             {
                 NumStatistics = new NumberStatistics();
                 var latestHeadChangeRecord = await _systemDatabaseService.GetLatestHeadChangeRecordAsync();
-                if (latestHeadChangeRecord!=null)
+                if (latestHeadChangeRecord != null)
                 {
                     NumStatistics.HeaderNum = latestHeadChangeRecord.CurrentLockCount;
                 }
-                
+
                 var latestNozzleChangeRecord = await _systemDatabaseService.GetLatestNozzleChangeRecordAsync();
-                if (latestNozzleChangeRecord!=null)
+                if (latestNozzleChangeRecord != null)
                 {
                     NumStatistics.NozzleNum = latestNozzleChangeRecord.CurrentLockCount;
                 }
-                
+
                 NumStatistics.Feeder1Num = _configService.GetRemainingCountByFeederNumber(1);
                 NumStatistics.Feeder2Num = _configService.GetRemainingCountByFeederNumber(2);
 
@@ -627,7 +627,7 @@ namespace TeamAAS_VP.Core
             }
             catch (Exception ex)
             {
-                SendTaskMessage(string.Format(Lang.电批连接失败0,ex.Message), MessageLevel.Alarm);
+                SendTaskMessage(string.Format(Lang.电批连接失败0, ex.Message), MessageLevel.Alarm);
                 LogHelper.WriteLogError(Lang.连接电批时出错, ex);
             }
         }
@@ -675,7 +675,7 @@ namespace TeamAAS_VP.Core
                 catch (Exception ex)
                 {
                     LogHelper.WriteLogError("初始化扭力测量仪时出错!", ex);
-                    SendTaskMessage("初始化扭力测量仪时出错!"+ex.Message, MessageLevel.Error);
+                    SendTaskMessage("初始化扭力测量仪时出错!" + ex.Message, MessageLevel.Error);
                 }
             }
             else
@@ -1227,7 +1227,7 @@ namespace TeamAAS_VP.Core
                 }
 
                 //获取产品编码
-                _productService.CurrentProductCode = plc.ReadNode<string>(string.Format(addressConfig.In_Code.Address,0));
+                _productService.CurrentProductCode = plc.ReadNode<string>(string.Format(addressConfig.In_Code.Address, 0));
                 //如果产品编码为空,则以当前的时间戳作为编码
                 if (string.IsNullOrEmpty(_productService.CurrentProductCode))
                 {
@@ -1277,7 +1277,7 @@ namespace TeamAAS_VP.Core
 
                             // 执行视觉任务
                             var _cts = new CancellationTokenSource();
-                            var visionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint(process, null, null, _cts.Token,null);
+                            var visionResult = await _remoteCommandService.ExecutePhotoGetSinglePoint(process, null, null, _cts.Token, null);
                             if (visionResult.IsSucceed)
                             {
                                 //披头偏差
@@ -1320,7 +1320,7 @@ namespace TeamAAS_VP.Core
                             SendTaskMessage(Lang.触发下相机拍照, MessageLevel.Debug);
                             //相机的编号
                             Int16 cameraIndex = plc.ReadNode<Int16>(addressConfig.In_DowmCameraNum.Address);
-                            SendTaskMessage(string.Format(Lang.编号0,cameraIndex), MessageLevel.Info);
+                            SendTaskMessage(string.Format(Lang.编号0, cameraIndex), MessageLevel.Info);
 
                             // 获取流程
                             var process = _productService.GetCurrentProductProcedureModelById(currentProduct.FixedUpCamera1ProcedureId);
@@ -1419,11 +1419,21 @@ namespace TeamAAS_VP.Core
                             Int16 cameraIndex = plc.ReadNode<Int16>(addressConfig.In_UpCameraPutNum.Address);
                             SendTaskMessage(string.Format(Lang.编号0, cameraIndex), MessageLevel.Info);
 
+                            //视觉流程ID
+                            Guid procedureId = currentProduct.MoveDownCameraLockPhotoProcedureId;
+
+                            //获取锁付拍照的点位
+                            var pos=currentProduct.ScrewCameraPoints.FirstOrDefault(p => p.Number == cameraIndex);
+                            if (pos != null)
+                            {
+                                procedureId= pos.VisionProcessID;
+                            }
+
                             // 获取流程
-                            var process = _productService.GetCurrentProductProcedureModelById(currentProduct.MoveDownCameraLockPhotoProcedureId);
+                            var process = _productService.GetCurrentProductProcedureModelById(procedureId);
                             if (process == null)
                             {
-                                SendTaskMessage(string.Format(Lang.未找到上相机锁附组装拍照对应的视觉流程流程ID0,currentProduct.MoveDownCameraLockPhotoProcedureId), MessageLevel.Alarm);
+                                SendTaskMessage(string.Format(Lang.未找到上相机锁附组装拍照对应的视觉流程流程ID0, procedureId), MessageLevel.Alarm);
                                 await plc.WriteNodeAsync(addressConfig.Out_UpCameraPutStatus.Address, (Int16)2);
                                 return;
                             }
@@ -1597,7 +1607,7 @@ namespace TeamAAS_VP.Core
                             SendTaskMessage(Lang.收到开始锁付信号, MessageLevel.Debug);
                             //位置编号
                             Int16 positionIndex = plc.ReadNode<Int16>(addressConfig.In_ProductNum.Address);
-                            SendTaskMessage(string.Format(Lang.编号0,positionIndex), MessageLevel.Info);
+                            SendTaskMessage(string.Format(Lang.编号0, positionIndex), MessageLevel.Info);
                         }
                         else
                         {
@@ -1624,7 +1634,7 @@ namespace TeamAAS_VP.Core
                             SendTaskMessage(Lang.收到停止锁付信号, MessageLevel.Debug);
                             //位置编号
                             Int16 positionIndex = plc.ReadNode<Int16>(addressConfig.In_ProductNum.Address);
-                            SendTaskMessage(string.Format(Lang.编号0,positionIndex), MessageLevel.Info);
+                            SendTaskMessage(string.Format(Lang.编号0, positionIndex), MessageLevel.Info);
                             //获取当前锁付点
                             var screwPoint = currentProduct.ScrewPoints.FirstOrDefault(p => p.Number == positionIndex);
                             //获取当前的机器人点位
@@ -1634,7 +1644,7 @@ namespace TeamAAS_VP.Core
                             float pressure = plc.ReadNode<float>(addressConfig.In_PressureValue.Address);
                             //当前用户名
                             string currentUserName = _systemDatabaseService.GetCurrentUser().UserName;
-                            
+
                             //吸嘴最后一次的记录
                             var nozzleRecord = await _systemDatabaseService.GetLatestNozzleChangeRecordAsync();
                             //最后一次的吸嘴编号
@@ -1703,9 +1713,9 @@ namespace TeamAAS_VP.Core
                             //记录锁付结果至数据库
                             await _systemDatabaseService.RecordLockResultAsync(lockResult);
                             //披头数量+1
-                            NumStatistics.HeaderNum=await _systemDatabaseService.IncrementLatestHeadLockCountAsync(currentUserName);
+                            NumStatistics.HeaderNum = await _systemDatabaseService.IncrementLatestHeadLockCountAsync(currentUserName);
                             //吸嘴数量+1
-                            NumStatistics.NozzleNum=await _systemDatabaseService.IncrementLatestNozzleLockCountAsync(currentUserName);
+                            NumStatistics.NozzleNum = await _systemDatabaseService.IncrementLatestNozzleLockCountAsync(currentUserName);
 
                             await plc.WriteNodeAsync(addressConfig.In_WorkDone.Address, (Int16)0);
                         }
@@ -1752,9 +1762,14 @@ namespace TeamAAS_VP.Core
 
                                 for (int i = 0; i < currentProduct.ScrewPoints.Count; i++)
                                 {
-                                    var localPoint = new PointF(currentProduct.ScrewPoints[i].X_Position, currentProduct.ScrewPoints[i].Y_Position);
+                                    var localPoint = new PointF(currentProduct.ScrewPoints[i].X_Position + currentProduct.ScrewPoints[i].X_Offset,
+                                        currentProduct.ScrewPoints[i].Y_Position + currentProduct.ScrewPoints[i].Y_Offset);
                                     var worldPoint = local.ToOldCoord(localPoint.X, localPoint.Y);
                                     var point = currentProduct.ScrewPoints[i].Clone();
+
+                                    //锁付点位在Local中已经加了偏移,这里写回PLC时需要将偏移清零,否则写入PLC端时会重复计算偏移
+                                    point.X_Offset = 0;
+                                    point.Y_Offset = 0;
                                     point.X_Position = (float)worldPoint[0];
                                     point.Y_Position = (float)worldPoint[1];
                                     SendTaskMessage($"点:{i},{point.X_Position:F3},{point.Y_Position:F4}", MessageLevel.Info);
@@ -1766,7 +1781,7 @@ namespace TeamAAS_VP.Core
                         }
                         else
                         {
-                            SendTaskMessage(string.Format(Lang.多相机坐标合并请求已结束或被取消state0,state), MessageLevel.Alarm);
+                            SendTaskMessage(string.Format(Lang.多相机坐标合并请求已结束或被取消state0, state), MessageLevel.Alarm);
                             await plc.WriteNodeAsync(addressConfig.Out_CameraDone.Address, (Int16)0);
                         }
                     }
@@ -1802,11 +1817,11 @@ namespace TeamAAS_VP.Core
                     }
                 }
                 // 过站检查
-                else 
+                else
                 {
                     for (int i = 0; i < 10; i++)
                     {
-                        if (string.Format(addressConfig.In_MesCheck.Address,i).Contains(tuple.nodeId))
+                        if (string.Format(addressConfig.In_MesCheck.Address, i).Contains(tuple.nodeId))
                         {
                             if (tuple.value is Int16 state)
                             {
@@ -1822,9 +1837,9 @@ namespace TeamAAS_VP.Core
                                 if (state == 1)
                                 {
                                     //这里缺少从MES获取产品配方的内容,需要补充
-                                    
 
-                                    
+
+
                                     (bool isSuccess, string response) = await _mesService.StationGetAsync(code, 2);
                                     if (i == 0)
                                     {
@@ -1856,7 +1871,7 @@ namespace TeamAAS_VP.Core
 
                                     //这里缺少上传MES的本站数据结果及开始和结束时间,需要补充
 
-                                    (bool isSuccess, string response) = await _mesService.SubmitGetAsync(code, true,DateTime.Now,DateTime.Now);
+                                    (bool isSuccess, string response) = await _mesService.SubmitGetAsync(code, true, DateTime.Now, DateTime.Now);
                                     //假设上传成功,这里缺少上传失败的处理
 
                                     await plc.WriteNodeAsync(string.Format(addressConfig.Out_MesStatus.Address, i), (Int16)3);
@@ -1869,7 +1884,7 @@ namespace TeamAAS_VP.Core
                             }
                         }
                     }
-                    
+
                 }
             }
             catch (Exception ex)

+ 157 - 7
TeamAAS-VM/Models/PLC/PlcPoint.cs

@@ -13,6 +13,9 @@ namespace TeamAAS_VP.Models.PLC
     public class PlcPoint : BindableBase
     {
         private int _Number;
+        /// <summary>
+        /// 点位编号
+        /// </summary>
         public int Number
         {
             get { return _Number; }
@@ -20,6 +23,9 @@ namespace TeamAAS_VP.Models.PLC
         }
 
         private string _Label;
+        /// <summary>
+        /// 点位标签
+        /// </summary>
         public string Label
         {
             get { return _Label; }
@@ -27,6 +33,9 @@ namespace TeamAAS_VP.Models.PLC
         }
 
         private float _X_Position;
+        /// <summary>
+        /// X轴位置
+        /// </summary>
         public float X_Position
         {
             get { return _X_Position; }
@@ -34,6 +43,9 @@ namespace TeamAAS_VP.Models.PLC
         }
 
         private float _X_Velocity;
+        /// <summary>
+        /// X轴速度
+        /// </summary>
         public float X_Velocity
         {
             get { return _X_Velocity; }
@@ -41,6 +53,9 @@ namespace TeamAAS_VP.Models.PLC
         }
 
         private float _Y_Position;
+        /// <summary>
+        /// Y轴位置
+        /// </summary>
         public float Y_Position
         {
             get { return _Y_Position; }
@@ -48,6 +63,9 @@ namespace TeamAAS_VP.Models.PLC
         }
 
         private float _Y_Velocity;
+        /// <summary>
+        /// Y轴速度
+        /// </summary>
         public float Y_Velocity
         {
             get { return _Y_Velocity; }
@@ -55,6 +73,9 @@ namespace TeamAAS_VP.Models.PLC
         }
 
         private float _Z_Position_Start;
+        /// <summary>
+        /// Z轴起点位置
+        /// </summary>
         public float Z_Position_Start
         {
             get { return _Z_Position_Start; }
@@ -62,6 +83,9 @@ namespace TeamAAS_VP.Models.PLC
         }
 
         private float _Z_Velocity_Start;
+        /// <summary>
+        /// Z轴起点速度
+        /// </summary>
         public float Z_Velocity_Start
         {
             get { return _Z_Velocity_Start; }
@@ -69,6 +93,9 @@ namespace TeamAAS_VP.Models.PLC
         }
 
         private float _Z_Position_Stop;
+        /// <summary>
+        /// Z轴终点位置
+        /// </summary>
         public float Z_Position_Stop
         {
             get { return _Z_Position_Stop; }
@@ -76,6 +103,9 @@ namespace TeamAAS_VP.Models.PLC
         }
 
         private float _Z_Velocity_Stop;
+        /// <summary>
+        /// Z轴终点速度
+        /// </summary>
         public float Z_Velocity_Stop
         {
             get { return _Z_Velocity_Stop; }
@@ -83,6 +113,9 @@ namespace TeamAAS_VP.Models.PLC
         }
 
         private float _U_Position;
+        /// <summary>
+        /// U轴位置
+        /// </summary>
         public float U_Position
         {
             get { return _U_Position; }
@@ -90,6 +123,9 @@ namespace TeamAAS_VP.Models.PLC
         }
 
         private float _U_Velocity;
+        /// <summary>
+        /// U轴速度
+        /// </summary>
         public float U_Velocity
         {
             get { return _U_Velocity; }
@@ -97,6 +133,9 @@ namespace TeamAAS_VP.Models.PLC
         }
 
         private float _R_Position;
+        /// <summary>
+        /// R轴位置
+        /// </summary>
         public float R_Position
         {
             get { return _R_Position; }
@@ -104,6 +143,9 @@ namespace TeamAAS_VP.Models.PLC
         }
 
         private float _R_Velocity;
+        /// <summary>
+        /// R轴速度
+        /// </summary>
         public float R_Velocity
         {
             get { return _R_Velocity; }
@@ -111,6 +153,9 @@ namespace TeamAAS_VP.Models.PLC
         }
 
         private float _Torque;
+        /// <summary>
+        /// 扭矩值
+        /// </summary>
         public float Torque
         {
             get { return _Torque; }
@@ -118,6 +163,9 @@ namespace TeamAAS_VP.Models.PLC
         }
 
         private Int16 _Feeder;
+        /// <summary>
+        /// Feeder编号
+        /// </summary>
         public Int16 Feeder
         {
             get { return _Feeder; }
@@ -125,6 +173,9 @@ namespace TeamAAS_VP.Models.PLC
         }
 
         private Int16 _ScrewProNum;
+        /// <summary>
+        /// 电批程序号
+        /// </summary>
         public Int16 ScrewProNum
         {
             get { return _ScrewProNum; }
@@ -133,12 +184,95 @@ namespace TeamAAS_VP.Models.PLC
 
         //描述
         private string _Description;
+        /// <summary>
+        /// 点位描述
+        /// </summary>
         public string Description
         {
             get { return _Description; }
             set { SetProperty(ref _Description, value); }
         }
 
+        private Guid _VisionProcessID;
+        /// <summary>
+        /// 视觉流程ID
+        /// </summary>
+        public Guid VisionProcessID
+        {
+            get { return _VisionProcessID; }
+            set { SetProperty(ref _VisionProcessID, value); }
+        }
+
+        private string _VisionProcessName;
+        /// <summary>
+        /// 视觉流程名称
+        /// </summary>
+        public string VisionProcessName
+        {
+            get { return _VisionProcessName; }
+            set { SetProperty(ref _VisionProcessName, value); }
+        }
+
+        private float _X_Offset;
+        /// <summary>
+        /// X轴补偿值
+        /// </summary>
+        public float X_Offset
+        {
+            get { return _X_Offset; }
+            set { SetProperty(ref _X_Offset, value); }
+        }
+
+        private float _Y_Offset;
+        /// <summary>
+        /// Y轴补偿值
+        /// </summary>
+        public float Y_Offset
+        {
+            get { return _Y_Offset; }
+            set { SetProperty(ref _Y_Offset, value); }
+        }
+
+        private float _Z_Start_Offset;
+        /// <summary>
+        /// Z轴起点补偿值
+        /// </summary>
+        public float Z_Start_Offset
+        {
+            get { return _Z_Start_Offset; }
+            set { SetProperty(ref _Z_Start_Offset, value); }
+        }
+
+        private float _Z_Stop_Offset;
+        /// <summary>
+        /// Z轴终点补偿值
+        /// </summary>
+        public float Z_Stop_Offset
+        {
+            get { return _Z_Stop_Offset; }
+            set { SetProperty(ref _Z_Stop_Offset, value); }
+        }
+
+        private float _U_Offset;
+        /// <summary>
+        /// U轴补偿值
+        /// </summary>
+        public float U_Offset
+        {
+            get { return _U_Offset; }
+            set { SetProperty(ref _U_Offset, value); }
+        }
+
+        private float _R_Offset;
+        /// <summary>
+        /// R轴补偿值
+        /// </summary>
+        public float R_Offset
+        {
+            get { return _R_Offset; }
+            set { SetProperty(ref _R_Offset, value); }
+        }
+
         public PlcPoint()
         {
             Number = 0;
@@ -157,6 +291,14 @@ namespace TeamAAS_VP.Models.PLC
             Torque = 0;
             Feeder = 0;
             ScrewProNum = 0;
+            Description = string.Empty;
+            X_Offset = 0;
+            Y_Offset = 0;
+            Z_Start_Offset = 0;
+            Z_Stop_Offset = 0;
+            U_Offset = 0;
+            R_Offset = 0;
+
         }
 
         public PlcPoint Clone()
@@ -180,7 +322,15 @@ namespace TeamAAS_VP.Models.PLC
                 Torque = this.Torque,
                 Feeder = this.Feeder,
                 ScrewProNum = this.ScrewProNum,
-                Description = this.Description
+                Description = this.Description,
+                VisionProcessID = this.VisionProcessID,
+                VisionProcessName = this.VisionProcessName,
+                X_Offset = this.X_Offset,
+                Y_Offset = this.Y_Offset,
+                Z_Start_Offset = this.Z_Start_Offset,
+                Z_Stop_Offset = this.Z_Stop_Offset,
+                U_Offset = this.U_Offset,
+                R_Offset = this.R_Offset
             };
         }
 
@@ -193,17 +343,17 @@ namespace TeamAAS_VP.Models.PLC
         public async Task<bool> WriteToPlcAddress(PlcPointAddress plcAddress, OpcUaClientPLC pLC)
         {
             Dictionary<string, object> nodeValues = new Dictionary<string, object>();
-            nodeValues.Add(string.Format(plcAddress.X_Position.Address, Number), X_Position);
+            nodeValues.Add(string.Format(plcAddress.X_Position.Address, Number), X_Position + X_Offset);
             nodeValues.Add(string.Format(plcAddress.X_Velocity.Address, Number), X_Velocity);
-            nodeValues.Add(string.Format(plcAddress.Y_Position.Address, Number), Y_Position);
+            nodeValues.Add(string.Format(plcAddress.Y_Position.Address, Number), Y_Position + Y_Offset);
             nodeValues.Add(string.Format(plcAddress.Y_Velocity.Address, Number), Y_Velocity);
-            nodeValues.Add(string.Format(plcAddress.Z_Position_Start.Address, Number), Z_Position_Start);
+            nodeValues.Add(string.Format(plcAddress.Z_Position_Start.Address, Number), Z_Position_Start + Z_Start_Offset);
             nodeValues.Add(string.Format(plcAddress.Z_Velocity_Start.Address, Number), Z_Velocity_Start);
-            nodeValues.Add(string.Format(plcAddress.Z_Position_Stop.Address, Number), Z_Position_Stop);
+            nodeValues.Add(string.Format(plcAddress.Z_Position_Stop.Address, Number), Z_Position_Stop + Z_Stop_Offset);
             nodeValues.Add(string.Format(plcAddress.Z_Velocity_Stop.Address, Number), Z_Velocity_Stop);
-            nodeValues.Add(string.Format(plcAddress.U_Position.Address, Number), U_Position);
+            nodeValues.Add(string.Format(plcAddress.U_Position.Address, Number), U_Position + U_Offset);
             nodeValues.Add(string.Format(plcAddress.U_Velocity.Address, Number), U_Velocity);
-            nodeValues.Add(string.Format(plcAddress.R_Position.Address, Number), R_Position);
+            nodeValues.Add(string.Format(plcAddress.R_Position.Address, Number), R_Position + R_Offset);
             nodeValues.Add(string.Format(plcAddress.R_Velocity.Address, Number), R_Velocity);
             nodeValues.Add(string.Format(plcAddress.Torque.Address, Number), Torque);
             nodeValues.Add(string.Format(plcAddress.Feeder.Address, Number), Feeder);

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

@@ -546,6 +546,7 @@
       <DependentUpon>Lang.resx</DependentUpon>
     </Compile>
     <Compile Include="Services\MesService.cs" />
+    <Compile Include="ViewModels\Product\PlcPointOffserParamsViewModel.cs" />
     <Compile Include="ViewModels\User\CardLoginWindowViewModel.cs" />
     <Compile Include="ViewModels\Home\ChangeNozzleViewModel.cs" />
     <Compile Include="ViewModels\Home\ChangeHeaderViewModel.cs" />
@@ -997,6 +998,9 @@
     <Compile Include="Views\Product\PalletManage.xaml.cs">
       <DependentUpon>PalletManage.xaml</DependentUpon>
     </Compile>
+    <Compile Include="Views\Product\PlcPointOffserParams.xaml.cs">
+      <DependentUpon>PlcPointOffserParams.xaml</DependentUpon>
+    </Compile>
     <Compile Include="Views\Product\PlcPointParams.xaml.cs">
       <DependentUpon>PlcPointParams.xaml</DependentUpon>
     </Compile>
@@ -1366,6 +1370,10 @@
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
     </Page>
+    <Page Include="Views\Product\PlcPointOffserParams.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
     <Page Include="Views\Product\PlcPointParams.xaml">
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>

+ 124 - 0
TeamAAS-VM/ViewModels/Product/PlcPointOffserParamsViewModel.cs

@@ -0,0 +1,124 @@
+using Prism.Commands;
+using Prism.Mvvm;
+using Prism.Services.Dialogs;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Windows;
+using TeamAAS_VP.Interfaces;
+using TeamAAS_VP.Models;
+using TeamAAS_VP.Models.PLC;
+using TeamAAS_VP.Resources.Languages;
+using TeamAAS_VP.Views.Setting;
+
+namespace TeamAAS_VP.ViewModels.Product
+{
+    public class PlcPointOffserParamsViewModel : BindableBase, IDialogAware
+    {
+
+        #region 属性
+        private ObservableCollection<PlcPoint> _Points = new ObservableCollection<PlcPoint>();
+        /// <summary>
+        /// 点位集合
+        /// </summary>
+        public ObservableCollection<PlcPoint> Points
+        {
+            get { return _Points; }
+            set { SetProperty(ref _Points, value); }
+        }
+        #endregion
+
+        #region 命令
+        private DelegateCommand _ConfirmCommand;
+        public DelegateCommand ConfirmCommand =>
+            _ConfirmCommand ?? (_ConfirmCommand = new DelegateCommand(ExecuteConfirmCommand, CanExecuteConfirmCommand));
+
+        private DelegateCommand _CancelCommand;
+        public DelegateCommand CancelCommand =>
+            _CancelCommand ?? (_CancelCommand = new DelegateCommand(ExecuteCancelCommand));
+
+        private DelegateCommand _ClearAllOffsetCommand;
+        public DelegateCommand ClearAllOffsetCommand =>
+            _ClearAllOffsetCommand ?? (_ClearAllOffsetCommand = new DelegateCommand(ExecuteClearAllOffsetCommand));
+
+
+        #endregion
+
+        public PlcPointOffserParamsViewModel()
+        {
+
+        }
+
+        /// <summary>
+        /// 确认按钮
+        /// </summary>
+        /// <returns></returns>
+        bool CanExecuteConfirmCommand()
+        {
+            return true;
+        }
+
+        void ExecuteConfirmCommand()
+        {
+            IDialogParameters parameters = new DialogParameters();
+            parameters.Add("Points", Points.ToArray());
+            RequestClose?.Invoke(new DialogResult(ButtonResult.OK, parameters));
+        }
+
+        /// <summary>
+        /// 取消按钮
+        /// </summary>
+        void ExecuteCancelCommand()
+        {
+            IDialogParameters parameters = new DialogParameters();
+            RequestClose?.Invoke(new DialogResult(ButtonResult.Cancel, parameters));
+        }
+
+        /// <summary>
+        /// 清除所有补偿值
+        /// </summary>
+        void ExecuteClearAllOffsetCommand()
+        {
+            foreach (var point in Points)
+            {
+                point.X_Offset = 0;
+                point.Y_Offset = 0;
+                point.Z_Start_Offset = 0;
+                point.Z_Stop_Offset = 0;
+                point.U_Offset = 0;
+                point.R_Offset = 0;
+            }
+
+        }
+
+        private string _Title;
+        public string Title
+        {
+            get { return _Title; }
+            set { SetProperty(ref _Title, value); }
+        }
+
+        public event Action<IDialogResult> RequestClose;
+
+        public bool CanCloseDialog()
+        {
+            return true;
+        }
+
+        public void OnDialogClosed()
+        {
+
+        }
+
+        public void OnDialogOpened(IDialogParameters parameters)
+        {
+            Title = parameters.GetValue<string>("Title");
+            var pts = parameters.GetValue<PlcPoint[]>("Points");
+            if (pts != null)
+            {
+                Points = new ObservableCollection<PlcPoint>(pts);
+            }
+        }
+    }
+}

+ 108 - 18
TeamAAS-VM/ViewModels/Product/PlcPointParamsViewModel.cs

@@ -45,7 +45,7 @@ namespace TeamAAS_VP.ViewModels.Product
         IRemoteCommandService _remoteCommandService;
         ICalibrationService _calibrationService;
         ICameraService _cameraService;
-        CoordinateTransformer local=null;
+        CoordinateTransformer local = null;
 
         #region 属性
 
@@ -292,10 +292,12 @@ namespace TeamAAS_VP.ViewModels.Product
         public CameraInfo SelectedCamera
         {
             get { return _SelectedCamera; }
-            set { SetProperty(ref _SelectedCamera, value);
-                if (value!=null)
+            set
+            {
+                SetProperty(ref _SelectedCamera, value);
+                if (value != null)
                 {
-                    if(Camera!=null)
+                    if (Camera != null)
                     {
                         if (Camera.IsGrabbing)
                         {
@@ -335,7 +337,9 @@ namespace TeamAAS_VP.ViewModels.Product
         public bool IsLeftDrawerOpen
         {
             get { return _IsLeftDrawerOpen; }
-            set { SetProperty(ref _IsLeftDrawerOpen, value);
+            set
+            {
+                SetProperty(ref _IsLeftDrawerOpen, value);
                 if (!value)
                 {
                     if (IsGrap)
@@ -438,7 +442,7 @@ namespace TeamAAS_VP.ViewModels.Product
 
         private DelegateCommand _StartGrabbingCommand;
         public DelegateCommand StartGrabbingCommand =>
-            _StartGrabbingCommand ?? (_StartGrabbingCommand = new DelegateCommand(ExecuteStartGrabbingCommand, CanExecuteStartGrabbingCommand).ObservesProperty(() => IsGrap).ObservesProperty(()=> SelectedCamera));
+            _StartGrabbingCommand ?? (_StartGrabbingCommand = new DelegateCommand(ExecuteStartGrabbingCommand, CanExecuteStartGrabbingCommand).ObservesProperty(() => IsGrap).ObservesProperty(() => SelectedCamera));
 
         private DelegateCommand _StopGrabbingCommand;
         public DelegateCommand StopGrabbingCommand =>
@@ -448,7 +452,11 @@ namespace TeamAAS_VP.ViewModels.Product
         public DelegateCommand DynamicTestAnalyzerCommand =>
             _DynamicTestAnalyzerCommand ?? (_DynamicTestAnalyzerCommand = new DelegateCommand(ExecuteDynamicTestAnalyzerCommand));
 
-        
+        private DelegateCommand _SetOffsetCommand;
+        public DelegateCommand SetOffsetCommand =>
+            _SetOffsetCommand ?? (_SetOffsetCommand = new DelegateCommand(ExecuteSetOffsetCommand));
+
+
         #endregion
 
         #region 事件
@@ -625,7 +633,7 @@ namespace TeamAAS_VP.ViewModels.Product
                             break;
                     }
                     //Robot.Timeout = 5000;
-                }    
+                }
                 _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = $"{Lang.完成}!", Duration = 0.4 });
             }
             catch (Exception ex)
@@ -657,7 +665,7 @@ namespace TeamAAS_VP.ViewModels.Product
                     }
 
                     //弹窗用户是否确认要示教该点位
-                    if (MessageBox.Show(string.Format(Lang.确认要示教点位0吗,SelectedPoint.Number), Lang.示教点位, MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes)
+                    if (MessageBox.Show(string.Format(Lang.确认要示教点位0吗, SelectedPoint.Number), Lang.示教点位, MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes)
                     {
                         return;
                     }
@@ -976,10 +984,17 @@ namespace TeamAAS_VP.ViewModels.Product
                         int startNumber = view.StartIndex;
 
                         //弹窗提示用户是否确认要导入从该编号开始的点位,点位数量为cadPoints.Count
-                        if (MessageBox.Show(string.Format(Lang.确认要从点位编号0开始导入1个点位吗, startNumber,cadPoints.Count), Lang.导入点位, MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes)
+                        if (MessageBox.Show(string.Format(Lang.确认要从点位编号0开始导入1个点位吗, startNumber, cadPoints.Count), Lang.导入点位, MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes)
                         {
                             return;
                         }
+                        //是否对原有点位的XY补偿值进行清零?
+                        bool clearCompensate = false;
+                        if (MessageBox.Show("是否对原有点位的XY补偿值进行清零?", Lang.确认, MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
+                        {
+                            clearCompensate = true;
+                        }
+
                         //导入点位
                         for (int i = 0; i < cadPoints.Count; i++)
                         {
@@ -990,7 +1005,11 @@ namespace TeamAAS_VP.ViewModels.Product
                             {
                                 existingPoint.X_Position = point.X;
                                 existingPoint.Y_Position = point.Y;
-
+                                if (clearCompensate)
+                                {
+                                    existingPoint.X_Offset = 0;
+                                    existingPoint.Y_Offset = 0;
+                                }
                             }
                             else
                             {
@@ -1171,7 +1190,7 @@ namespace TeamAAS_VP.ViewModels.Product
             {
                 if (point.Z_Position_Stop >= point.Z_Position_Start)
                 {
-                    MessageBox.Show(string.Format(Lang.点位编号0的终点坐标大于等于起始坐标请调整终点坐标, point.Number ), Lang.警告, MessageBoxButton.OK, MessageBoxImage.Warning);
+                    MessageBox.Show(string.Format(Lang.点位编号0的终点坐标大于等于起始坐标请调整终点坐标, point.Number), Lang.警告, MessageBoxButton.OK, MessageBoxImage.Warning);
                 }
             }
 
@@ -1246,8 +1265,8 @@ namespace TeamAAS_VP.ViewModels.Product
                     if (result1 == ButtonResult.OK)
                     {
                         var param = rst.Parameters.GetValue<ObservableCollection<PointEx>>("CorrectPoints");
-                        var local1= rst.Parameters.GetValue<CoordinateTransformer>("Local");
-                        if (local1!=null)
+                        var local1 = rst.Parameters.GetValue<CoordinateTransformer>("Local");
+                        if (local1 != null)
                         {
                             local = local1;
                         }
@@ -1255,6 +1274,9 @@ namespace TeamAAS_VP.ViewModels.Product
                         {
                             SelectProduct.ScrewPoints[i].X_Position = param[i].PostX;
                             SelectProduct.ScrewPoints[i].Y_Position = param[i].PostY;
+                            //XY的补偿值清零
+                            SelectProduct.ScrewPoints[i].X_Offset = 0;
+                            SelectProduct.ScrewPoints[i].Y_Offset = 0;
                         }
 
                         _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = Lang.完成, Duration = 1 });
@@ -1309,7 +1331,7 @@ namespace TeamAAS_VP.ViewModels.Product
                 }
 
 
-                
+
                 //如果当前Local为空,则自动进行锁付点位的Local计算
                 if (local == null)
                 {
@@ -1545,7 +1567,7 @@ namespace TeamAAS_VP.ViewModels.Product
         /// </summary>
         void ExecuteStopGrabbingCommand()
         {
-            
+
             if (Camera != null)
                 Camera.StopGrabbing();
             IsGrap = false;
@@ -1586,6 +1608,74 @@ namespace TeamAAS_VP.ViewModels.Product
                      }
                  }));
         }
+
+        /// <summary>
+        /// 设置偏移
+        /// </summary>
+        void ExecuteSetOffsetCommand()
+        {
+            if (SelectedIndex<0) return;
+            IDialogParameters parameters1 = new DialogParameters();
+            if (SelectedIndex == 0)
+            {
+                parameters1.Add("Title", "取料拍照点位-补偿值设置");
+            }
+            else if (SelectedIndex == 1)
+            {
+                parameters1.Add("Title", "取料点位-补偿值设置");
+            }
+            else if (SelectedIndex == 2)
+            {
+                parameters1.Add("Title", "下相机二次定位点位-补偿值设置");
+            }
+            else if (SelectedIndex == 3)
+            {
+                parameters1.Add("Title", "锁附拍照点位-补偿值设置");
+            }
+            else if (SelectedIndex == 4)
+            {
+                parameters1.Add("Title", "锁附点位-补偿值设置");
+            }
+            else if (SelectedIndex == 5)
+            {
+                parameters1.Add("Title", "复检点位-补偿值设置");
+            }
+            else
+            {
+                parameters1.Add("Title", "点位-补偿值设置");
+            }
+
+            List<PlcPoint> _points = new List<PlcPoint>();
+            foreach (var item in Points)
+            {
+                _points.Add(item.Clone());
+            }
+            parameters1.Add("Points", _points.ToArray());
+            _dialogService.ShowDialog("PlcPointOffserParams", parameters1, rst =>
+            {
+                //对话框关闭之后的回调函数,可以在这解析结果。
+                ButtonResult result1 = rst.Result;
+
+                if (result1 == ButtonResult.OK)
+                {
+                    var param = rst.Parameters.GetValue<PlcPoint[]>("Points");
+
+                    //更新点位
+                    for (int i = 0; i < Points.Count; i++)
+                    {
+                        Points[i].X_Offset = param[i].X_Offset;
+                        Points[i].Y_Offset = param[i].Y_Offset;
+                        Points[i].Z_Start_Offset = param[i].Z_Start_Offset;
+                        Points[i].Z_Stop_Offset = param[i].Z_Stop_Offset;
+                        Points[i].U_Offset = param[i].U_Offset;
+                        Points[i].R_Offset = param[i].R_Offset;
+                    }
+
+                    _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = $"{Lang.完成}", Duration = 1 });
+                }
+
+            });
+        }
         #endregion
 
         #region 继承
@@ -1649,7 +1739,7 @@ namespace TeamAAS_VP.ViewModels.Product
                 LockScrewProgramNumber = SelectProduct.ScrewPoints.FirstOrDefault()?.ScrewProNum ?? 1;
 
                 CameraList = new ObservableCollection<CameraInfo>(_configService.GetAllCameras());
-               
+
             }
             catch (Exception ex)
             {
@@ -1687,7 +1777,7 @@ namespace TeamAAS_VP.ViewModels.Product
                         Camera.StopGrabbing();
                     }
                     Camera.ImageCallbackEvent -= Camera_ImageCallbackEvent;
-                    
+
                     Camera = null;
                 }
                 SelectedCamera = null;

+ 319 - 0
TeamAAS-VM/Views/Product/PlcPointOffserParams.xaml

@@ -0,0 +1,319 @@
+<UserControl x:Class="TeamAAS_VP.Views.Product.PlcPointOffserParams"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:prism="http://prismlibrary.com/"
+             prism:ViewModelLocator.AutoWireViewModel="True"
+             xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+             xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
+             xmlns:system="clr-namespace:System;assembly=mscorlib"
+             xmlns:local="clr-namespace:TeamAAS_VP.Controls"
+             xmlns:vm="clr-namespace:TeamAAS_VP.ViewModels.Product"
+             xmlns:lex="http://wpflocalizeextension.codeplex.com"
+             lex:LocalizeDictionary.DesignCulture="zh-CN"
+             lex:ResxLocalizationProvider.DefaultAssembly="TeamAAS-VP"
+             lex:ResxLocalizationProvider.DefaultDictionary="Lang"
+             mc:Ignorable="d"
+             d:DesignHeight="768"
+             d:DesignWidth="1024"
+             d:Background="White"
+             MaxHeight="1000"
+             MaxWidth="1840"
+             d:DataContext="{d:DesignInstance Type=vm:PlcPointOffserParamsViewModel}"
+             FontFamily="{DynamicResource DefaultFont}">
+    <prism:Dialog.WindowStyle>
+        <Style TargetType="Window">
+            <Setter Property="prism:Dialog.WindowStartupLocation"
+                    Value="CenterScreen" />
+            <!--<Setter Property="WindowChrome.WindowChrome">
+            <Setter.Value>
+                <WindowChrome CaptionHeight="0"
+                              ResizeBorderThickness="1" />
+            </Setter.Value>
+        </Setter>-->
+            <Setter Property="WindowStyle"
+                    Value="None" />
+            <Setter Property="AllowDrop"
+                    Value="True" />
+            <Setter Property="BorderThickness"
+                    Value="0" />
+            <Setter Property="ShowInTaskbar"
+                    Value="False" />
+            <Setter Property="SizeToContent"
+                    Value="WidthAndHeight" />
+            <Setter Property="WindowState"
+                    Value="Normal" />
+            <Setter Property="Topmost"
+                    Value="True" />
+        </Style>
+    </prism:Dialog.WindowStyle>
+    <Grid Margin="16">
+        <Grid.RowDefinitions>
+            <RowDefinition Height="auto" />
+            <RowDefinition Height="*" />
+            <RowDefinition Height="auto" />
+        </Grid.RowDefinitions>
+        <TextBlock Text="{Binding Title}"
+                   FontSize="16"
+                   FontWeight="Bold"
+                   Margin="0,10"
+                   VerticalAlignment="Center"
+                   TextAlignment="Left"
+                   HorizontalAlignment="Left" />
+        <!--点位表-->
+        <Border Grid.Row="1"
+                BorderBrush="#D0D0D0"
+                BorderThickness="1"
+                Margin="0,5">
+            <DataGrid x:Name="dgPoints"
+                      AutoGenerateColumns="False"
+                      CanUserAddRows="False"
+                      CanUserDeleteRows="False"
+                      ColumnWidth="*"
+                      SelectionUnit="FullRow"
+                      SelectionMode="Single"
+                      ItemsSource="{Binding Points}"
+                      HeadersVisibility="Column"
+                      HorizontalScrollBarVisibility="Auto"
+                      ScrollViewer.CanContentScroll="True"
+                      ScrollViewer.HorizontalScrollBarVisibility="Auto"
+                      GridLinesVisibility="All"
+                      VerticalGridLinesBrush="#D0D0D0">
+                <DataGrid.Resources>
+                    <Style TargetType="DataGridCell">
+                        <Style.Resources>
+                            <SolidColorBrush  x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}"
+                                              Color="#0078D7" />
+                        </Style.Resources>
+                        <Setter Property="MinHeight"
+                                Value="25" />
+                        <Setter Property="VerticalContentAlignment"
+                                Value="Center" />
+                        <Setter Property="HorizontalContentAlignment"
+                                Value="Center" />
+                        <Setter Property="VerticalAlignment"
+                                Value="Center" />
+                        <Setter Property="TextBlock.TextAlignment"
+                                Value="Center" />
+                        <Setter Property="Padding"
+                                Value="0" />
+                        <Style.Triggers>
+                            <Trigger Property="IsSelected"
+                                     Value="True">
+                                <Setter Property="Foreground"
+                                        Value="White" />
+                            </Trigger>
+                        </Style.Triggers>
+                    </Style>
+
+                    <!-- 为 TextBlock 添加默认居中样式 -->
+                    <Style TargetType="TextBlock">
+                        <Setter Property="TextAlignment"
+                                Value="Center" />
+                        <Setter Property="HorizontalAlignment"
+                                Value="Center" />
+                        <Setter Property="VerticalAlignment"
+                                Value="Center" />
+                    </Style>
+                </DataGrid.Resources>
+                <DataGrid.Columns>
+                    <DataGridTextColumn Header="{lex:Loc 编号}"
+                                        IsReadOnly="True"
+                                        MinWidth="60"
+                                        Width="Auto"
+                                        Binding="{Binding Number, Mode=TwoWay, StringFormat={}{0:F0}}">
+                    </DataGridTextColumn>
+                    <DataGridTextColumn Header="{lex:Loc 标签}"
+                                        MinWidth="100"
+                                        Width="Auto"
+                                        Binding="{Binding Label, Mode=TwoWay}" />
+                    <!--X 坐标-->
+                    <DataGridTemplateColumn Header="X补偿"
+                                            MinWidth="60"
+                                            Width="Auto">
+                        <DataGridTemplateColumn.CellTemplate>
+                            <DataTemplate>
+                                <TextBlock Text="{Binding X_Offset, StringFormat={}{0:F3}}"
+                                           HorizontalAlignment="Center"
+                                           VerticalAlignment="Center" />
+                            </DataTemplate>
+                        </DataGridTemplateColumn.CellTemplate>
+                        <DataGridTemplateColumn.CellEditingTemplate>
+                            <DataTemplate>
+                                <mah:NumericUpDown Value="{Binding X_Offset, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
+                                                   Minimum="-9999.000"
+                                                   Maximum="9999.000"
+                                                   Interval="0.1"
+                                                   StringFormat="F3"
+                                                   HorizontalAlignment="Stretch"
+                                                   VerticalAlignment="Center"
+                                                   Margin="0"
+                                                   Padding="2" />
+                            </DataTemplate>
+                        </DataGridTemplateColumn.CellEditingTemplate>
+                    </DataGridTemplateColumn>
+                    <!--Y 坐标-->
+                    <DataGridTemplateColumn Header="Y补偿"
+                                            MinWidth="60"
+                                            Width="Auto">
+                        <DataGridTemplateColumn.CellTemplate>
+                            <DataTemplate>
+                                <TextBlock Text="{Binding Y_Offset, StringFormat={}{0:F3}}"
+                                           HorizontalAlignment="Center"
+                                           VerticalAlignment="Center" />
+                            </DataTemplate>
+                        </DataGridTemplateColumn.CellTemplate>
+                        <DataGridTemplateColumn.CellEditingTemplate>
+                            <DataTemplate>
+                                <mah:NumericUpDown Value="{Binding Y_Offset, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
+                                                   Minimum="-9999.000"
+                                                   Maximum="9999.000"
+                                                   Interval="0.1"
+                                                   StringFormat="F3"
+                                                   HorizontalAlignment="Stretch"
+                                                   VerticalAlignment="Center"
+                                                   Margin="0"
+                                                   Padding="2" />
+                            </DataTemplate>
+                        </DataGridTemplateColumn.CellEditingTemplate>
+                    </DataGridTemplateColumn>
+                    <!--Z 起点坐标-->
+                    <DataGridTemplateColumn Header="Z起点补偿"
+                                            MinWidth="60"
+                                            Width="Auto">
+                        <DataGridTemplateColumn.CellTemplate>
+                            <DataTemplate>
+                                <TextBlock Text="{Binding Z_Start_Offset, StringFormat={}{0:F3}}"
+                                           HorizontalAlignment="Center"
+                                           VerticalAlignment="Center" />
+                            </DataTemplate>
+                        </DataGridTemplateColumn.CellTemplate>
+                        <DataGridTemplateColumn.CellEditingTemplate>
+                            <DataTemplate>
+                                <mah:NumericUpDown Value="{Binding Z_Start_Offset, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
+                                                   Minimum="-9999.000"
+                                                   Maximum="9999.000"
+                                                   Interval="0.1"
+                                                   StringFormat="F3"
+                                                   HorizontalAlignment="Stretch"
+                                                   VerticalAlignment="Center"
+                                                   Margin="0"
+                                                   Padding="2" />
+                            </DataTemplate>
+                        </DataGridTemplateColumn.CellEditingTemplate>
+                    </DataGridTemplateColumn>
+                    <!--Z 终点坐标-->
+                    <DataGridTemplateColumn Header="Z终点补偿"
+                                            MinWidth="60"
+                                            Width="Auto">
+                        <DataGridTemplateColumn.CellTemplate>
+                            <DataTemplate>
+                                <TextBlock Text="{Binding Z_Stop_Offset, StringFormat={}{0:F3}}"
+                                           HorizontalAlignment="Center"
+                                           VerticalAlignment="Center" />
+                            </DataTemplate>
+                        </DataGridTemplateColumn.CellTemplate>
+                        <DataGridTemplateColumn.CellEditingTemplate>
+                            <DataTemplate>
+                                <mah:NumericUpDown Value="{Binding Z_Stop_Offset, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
+                                                   Minimum="-9999.000"
+                                                   Maximum="9999.000"
+                                                   Interval="0.1"
+                                                   StringFormat="F3"
+                                                   HorizontalAlignment="Stretch"
+                                                   VerticalAlignment="Center"
+                                                   Margin="0"
+                                                   Padding="2" />
+                            </DataTemplate>
+                        </DataGridTemplateColumn.CellEditingTemplate>
+                    </DataGridTemplateColumn>
+                    <!--U 坐标-->
+                    <DataGridTemplateColumn Header="U补偿"
+                                            MinWidth="60"
+                                            Width="Auto">
+                        <DataGridTemplateColumn.CellTemplate>
+                            <DataTemplate>
+                                <TextBlock Text="{Binding U_Offset, StringFormat={}{0:F3}}"
+                                           HorizontalAlignment="Center"
+                                           VerticalAlignment="Center" />
+                            </DataTemplate>
+                        </DataGridTemplateColumn.CellTemplate>
+                        <DataGridTemplateColumn.CellEditingTemplate>
+                            <DataTemplate>
+                                <mah:NumericUpDown Value="{Binding U_Offset, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
+                                                   Minimum="-9999.000"
+                                                   Maximum="9999.000"
+                                                   Interval="0.1"
+                                                   StringFormat="F3"
+                                                   HorizontalAlignment="Stretch"
+                                                   VerticalAlignment="Center"
+                                                   Margin="0"
+                                                   Padding="2" />
+                            </DataTemplate>
+                        </DataGridTemplateColumn.CellEditingTemplate>
+                    </DataGridTemplateColumn>
+                    <!--R 坐标-->
+                    <DataGridTemplateColumn Header="R补偿"
+                                            MinWidth="60"
+                                            Width="Auto">
+                        <DataGridTemplateColumn.CellTemplate>
+                            <DataTemplate>
+                                <TextBlock Text="{Binding R_Offset, StringFormat={}{0:F3}}"
+                                           HorizontalAlignment="Center"
+                                           VerticalAlignment="Center" />
+                            </DataTemplate>
+                        </DataGridTemplateColumn.CellTemplate>
+                        <DataGridTemplateColumn.CellEditingTemplate>
+                            <DataTemplate>
+                                <mah:NumericUpDown Value="{Binding R_Offset, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
+                                                   Minimum="-9999.000"
+                                                   Maximum="9999.000"
+                                                   Interval="0.1"
+                                                   StringFormat="F3"
+                                                   HorizontalAlignment="Stretch"
+                                                   VerticalAlignment="Center"
+                                                   Margin="0"
+                                                   Padding="2" />
+                            </DataTemplate>
+                        </DataGridTemplateColumn.CellEditingTemplate>
+                    </DataGridTemplateColumn>
+
+                    <DataGridTextColumn Header="{lex:Loc 描述}"
+                                        MinWidth="100"
+                                        Width="200"
+                                        Binding="{Binding Description, Mode=TwoWay}" />
+                </DataGrid.Columns>
+            </DataGrid>
+        </Border>
+        <StackPanel Grid.Row="2"
+                    Orientation="Horizontal"
+                    HorizontalAlignment="Right">
+            <!--清除所有补偿-->
+            <Button Height="30"
+                    Margin="0,0,20,0"
+                    materialDesign:ButtonAssist.CornerRadius="10"
+                    Style="{StaticResource MaterialDesignRaisedButton}"
+                    ToolTip="清除所有补偿"
+                    Command="{Binding ClearAllOffsetCommand}">
+                <TextBlock Text="清除所有补偿" />
+            </Button>
+
+            <Button Height="30"
+                    materialDesign:ButtonAssist.CornerRadius="10"
+                    Style="{StaticResource MaterialDesignRaisedButton}"
+                    ToolTip="{lex:Loc 确定}"
+                    Command="{Binding ConfirmCommand}">
+                <TextBlock Text="{lex:Loc 确定}" />
+            </Button>
+            <Button Height="30"
+                    Margin="20,0"
+                    materialDesign:ButtonAssist.CornerRadius="10"
+                    Style="{StaticResource MaterialDesignRaisedButton}"
+                    ToolTip="{lex:Loc 取消}"
+                    Command="{Binding CancelCommand}">
+                <TextBlock Text="{lex:Loc 取消}" />
+            </Button>
+        </StackPanel>
+    </Grid>
+</UserControl>

+ 15 - 0
TeamAAS-VM/Views/Product/PlcPointOffserParams.xaml.cs

@@ -0,0 +1,15 @@
+using System.Windows.Controls;
+
+namespace TeamAAS_VP.Views.Product
+{
+    /// <summary>
+    /// Interaction logic for PlcPointOffserParams
+    /// </summary>
+    public partial class PlcPointOffserParams : UserControl
+    {
+        public PlcPointOffserParams()
+        {
+            InitializeComponent();
+        }
+    }
+}

+ 59 - 6
TeamAAS-VM/Views/Product/PlcPointParams.xaml

@@ -125,8 +125,7 @@
                                 Orientation="Horizontal">
                         <TextBlock Text="{lex:Loc 相机,Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0}: '}"
                                    FontWeight="Bold"
-                                   VerticalAlignment="Center"
-                                   />
+                                   VerticalAlignment="Center" />
                         <ComboBox Margin="5,0,10,0"
                                   IsEnabled="{Binding IsGrap,Converter={StaticResource InvertBooleanConverter}}"
                                   ItemsSource="{Binding CameraList}"
@@ -162,7 +161,7 @@
                                    Foreground="Gray" />
                     </StackPanel>
                 </Grid>
-                
+
             </materialDesign:DrawerHost.LeftDrawerContent>
             <Grid>
                 <Grid.ColumnDefinitions>
@@ -330,6 +329,31 @@
                                     </Style>
                                 </Button.Style>
                             </Button>
+                            <!--设置补偿值-->
+                            <Button Content="设置补偿值"
+                                    Margin="5,2"
+                                    MinWidth="80"
+                                    d:Visibility="Visible"
+                                    materialDesign:ButtonAssist.CornerRadius="5"
+                                    Command="{Binding SetOffsetCommand}">
+                                <!--<Button.Style>
+                                    <Style TargetType="Button"
+                                           BasedOn="{StaticResource MaterialDesignRaisedDarkButton}">
+                                        <Setter Property="Visibility"
+                                                Value="Collapsed" />
+                                        <Style.Triggers>
+                                            -->
+                                <!-- 当 SelectedIndex == 0 时显示此面板 -->
+                                <!--
+                                            <DataTrigger Binding="{Binding SelectedIndex}"
+                                                         Value="1">
+                                                <Setter Property="Visibility"
+                                                        Value="Visible" />
+                                            </DataTrigger>
+                                        </Style.Triggers>
+                                    </Style>
+                                </Button.Style>-->
+                            </Button>
                         </StackPanel>
                         <Border BorderBrush="LightGray"
                                 BorderThickness="1"
@@ -1259,6 +1283,35 @@
                                             </DataTemplate>
                                         </DataGridTemplateColumn.CellEditingTemplate>
                                     </DataGridTemplateColumn>
+                                    <!--视觉流程-->
+                                    <DataGridTemplateColumn x:Name="colProcedure"
+                                                            Header="视觉流程"
+                                                            MinWidth="60"
+                                                            Width="Auto">
+                                        <DataGridTemplateColumn.CellTemplate>
+                                            <DataTemplate>
+                                                <ComboBox MinWidth="50"
+                                                          Margin="5,0,0,0"
+                                                          ItemsSource="{Binding DataContext.ProcedureModels,RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
+                                                          SelectedValuePath="Id"
+                                                          SelectedValue="{Binding VisionProcessID, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
+                                                          SelectionChanged="ProcedureCombo_SelectionChanged">
+                                                    <ComboBox.ItemTemplate>
+                                                        <DataTemplate>
+                                                            <StackPanel Orientation="Horizontal">
+                                                                <materialDesign:PackIcon Kind="VideoOutline" />
+                                                                <TextBlock Text="{Binding CameraName}"
+                                                                           Margin="6,0" />
+                                                                <materialDesign:PackIcon Kind="ProgressWrench" />
+                                                                <TextBlock Text="{Binding Name}"
+                                                                           Margin="6,0" />
+                                                            </StackPanel>
+                                                        </DataTemplate>
+                                                    </ComboBox.ItemTemplate>
+                                                </ComboBox>
+                                            </DataTemplate>
+                                        </DataGridTemplateColumn.CellTemplate>
+                                    </DataGridTemplateColumn>
 
                                     <DataGridTextColumn Header="{lex:Loc 描述}"
                                                         MinWidth="100"
@@ -1286,7 +1339,7 @@
                             <ToggleButton Grid.ColumnSpan="2"
                                           HorizontalAlignment="Left"
                                           VerticalAlignment="Top"
-                                         materialDesign:ToggleButtonAssist.OnContent="{materialDesign:PackIcon Kind=ArrowLeft}"
+                                          materialDesign:ToggleButtonAssist.OnContent="{materialDesign:PackIcon Kind=ArrowLeft}"
                                           Content="{materialDesign:PackIcon Kind=Camera}"
                                           Style="{StaticResource MaterialDesignActionToggleButton}"
                                           ToolTip="{lex:Loc 相机图像}"
@@ -1301,8 +1354,8 @@
                                     <RowDefinition Height="auto" />
                                     <RowDefinition Height="auto" />
                                 </Grid.RowDefinitions>
-                                
-                                
+
+
                                 <Button Content="{lex:Loc 上使能}"
                                         Grid.Row="0"
                                         materialDesign:ButtonAssist.CornerRadius="10"

+ 42 - 0
TeamAAS-VM/Views/Product/PlcPointParams.xaml.cs

@@ -19,12 +19,54 @@ namespace TeamAAS_VP.Views.Product
             InitializeComponent();
             VM = DataContext as PlcPointParamsViewModel;
             VM.PropertyChanged += VM_PropertyChanged;
+            VM.PropertyChanged += Vm_SelectedIndexChanged;
+            // initialize visibility
+            try
+            {
+                if (VM != null && colProcedure != null)
+                    colProcedure.Visibility = VM.SelectedIndex == 3 ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
+            }
+            catch { }
             this.display.HorizontalScrollBar = false;
             this.display.VerticalScrollBar = false;
             this.display.AutoFit = true;
             this.display.BackColor = System.Drawing.SystemColors.ActiveCaption;
         }
 
+        private void Vm_SelectedIndexChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
+        {
+            if (e.PropertyName == nameof(PlcPointParamsViewModel.SelectedIndex))
+            {
+                try
+                {
+                    var visible = VM.SelectedIndex == 3 ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
+                    this.Dispatcher.BeginInvoke(new Action(() =>
+                    {
+                        if (colProcedure != null)
+                            colProcedure.Visibility = visible;
+                    }));
+                }
+                catch { }
+            }
+        }
+
+        private void ProcedureCombo_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
+        {
+            try
+            {
+                var combo = sender as System.Windows.Controls.ComboBox;
+                if (combo == null) return;
+                var proc = combo.SelectedItem as TeamAAS_VP.Models.ProcedureModel;
+                var point = combo.DataContext as TeamAAS_VP.Models.PLC.PlcPoint;
+                if (point != null && proc != null)
+                {
+                    // SelectedValue binding already sets VisionProcessID; sync name
+                    point.VisionProcessName = proc.Name;
+                }
+            }
+            catch { }
+        }
+
         private int _imageWidth;
         private int _imageHeight;
         private void VM_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)