Explorar o código

自定义图片文件名与工位级CTQ配置支持

新增图片文件名模板功能,支持变量与格式化;DeviceInfo增加工位级CTQ配置,移除全局CTQ;视觉接口参数优化,支持多次拍照区分;数据保存支持多CTQ项批量写入;界面增强图片命名预览与CTQ配置项;版本号升级至1.2.1.5。
徐孝锋 hai 7 meses
pai
achega
94e662ad61

+ 98 - 0
TeamAAS-VM/Core/FileNameTemplate.cs

@@ -0,0 +1,98 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+namespace TeamAAS_VP.Core
+{
+    public class FileNameTemplate
+    {
+        private readonly string _template;
+        private readonly Dictionary<string, Func<object>> _variables;
+
+        public FileNameTemplate(string template)
+        {
+            _template = template ?? throw new ArgumentNullException(nameof(template));
+            _variables = new Dictionary<string, Func<object>>(StringComparer.OrdinalIgnoreCase);
+
+            // 注册内置变量
+            RegisterDefaultVariables();
+        }
+
+        // 注册自定义变量
+        public void RegisterVariable(string name, Func<object> valueProvider)
+        {
+            _variables[name] = valueProvider ?? throw new ArgumentNullException(nameof(valueProvider));
+        }
+
+        // 生成文件名
+        public string Generate()
+        {
+            string result = _template;
+
+            // 查找所有 {变量名[:格式化字符串]} 格式的占位符
+            var matches = Regex.Matches(_template, @"\{([^}:]+)(?::([^}]+))?\}");
+
+            foreach (Match match in matches)
+            {
+                string fullPlaceholder = match.Value;
+                string varName = match.Groups[1].Value;
+                string format = match.Groups[2].Success ? match.Groups[2].Value : null;
+
+                if (_variables.TryGetValue(varName, out var valueProvider))
+                {
+                    object value = valueProvider();
+                    string replacement = FormatValue(value, format);
+                    result = result.Replace(fullPlaceholder, replacement);
+                }
+            }
+
+            // 移除文件名中不允许的字符
+            result = SanitizeFileName(result);
+
+            return result;
+        }
+
+        private string FormatValue(object value, string format)
+        {
+            if (value == null) return "";
+
+            // 如果是日期时间类型,应用格式
+            if (value is DateTime dateTime && !string.IsNullOrEmpty(format))
+            {
+                return dateTime.ToString(format);
+            }
+
+            // 如果是数值类型,应用格式
+            if (value is IFormattable formattable && !string.IsNullOrEmpty(format))
+            {
+                return formattable.ToString(format, null);
+            }
+
+            return value.ToString();
+        }
+
+        private string SanitizeFileName(string fileName)
+        {
+            // 移除文件名中不允许的字符
+            char[] invalidChars = System.IO.Path.GetInvalidFileNameChars();
+            foreach (char c in invalidChars)
+            {
+                fileName = fileName.Replace(c.ToString(), "");
+            }
+            return fileName;
+        }
+
+        private void RegisterDefaultVariables()
+        {
+            // 日期时间变量
+            RegisterVariable("Now", () => DateTime.Now);
+            RegisterVariable("Today", () => DateTime.Today);
+            RegisterVariable("UtcNow", () => DateTime.UtcNow);
+
+            // 可以在这里添加更多内置变量
+        }
+    }
+}

+ 66 - 29
TeamAAS-VM/Core/Management.cs

@@ -1290,13 +1290,13 @@ namespace TeamAAS_VP.Core
                     return;
                 }
 
-                //获取产品编码
-                _productService.CurrentProductCode = plc.ReadNode<string>(string.Format(addressConfig.In_Code.Address, 0));
-                //如果产品编码为空,则以当前的时间戳作为编码
-                if (string.IsNullOrEmpty(_productService.CurrentProductCode))
-                {
-                    _productService.CurrentProductCode = DateTime.Now.ToString("yyyyMMddHHmmssfff");
-                }
+                ////获取产品编码
+                //_productService.CurrentProductCode = plc.ReadNode<string>(string.Format(addressConfig.In_Code.Address, 0));
+                ////如果产品编码为空,则以当前的时间戳作为编码
+                //if (string.IsNullOrEmpty(_productService.CurrentProductCode))
+                //{
+                //    _productService.CurrentProductCode = DateTime.Now.ToString("yyyyMMddHHmmssfff");
+                //}
 
                 bool isDryMode = plc.ReadNode<bool>(addressConfig.In_DryMode.Address);
 
@@ -1883,7 +1883,7 @@ namespace TeamAAS_VP.Core
 
                             // 执行视觉任务
                             var _cts = new CancellationTokenSource();
-                            var visionResult = await _remoteCommandService.ExecutePhotoGetDistance(process, null, new double[] { currentPosition.X, currentPosition.Y, currentPosition.U }, _cts.Token, cameraIndex, null);
+                            var visionResult = await _remoteCommandService.ExecutePhotoGetDistance(1,process, null, new double[] { currentPosition.X, currentPosition.Y, currentPosition.U }, _cts.Token, cameraIndex, null);
                             if (visionResult.distance.Split(',')[0] == "1")
                             {
                                 mes_cc.Clear();
@@ -2270,6 +2270,10 @@ namespace TeamAAS_VP.Core
                                                     if (snItem != null)
                                                     {
                                                         ProductMainSN[i] = snItem.Replace("sn=", "").Trim();
+                                                        if (i == 0)
+                                                        {
+                                                            _productService.CurrentProductCode = ProductMainSN[i];
+                                                        }
                                                         SendTaskMessage($"产品主sn:{ProductMainSN[i]}", MessageLevel.Info);
                                                     }
                                                     string woItem = item.FirstOrDefault(f => f.Contains("wo="));
@@ -2327,6 +2331,10 @@ namespace TeamAAS_VP.Core
                                                 if (snItem != null)
                                                 {
                                                     ProductMainSN[i] = snItem.Replace("sn=", "").Trim();
+                                                    if (i == 0)
+                                                    {
+                                                        _productService.CurrentProductCode = ProductMainSN[i];
+                                                    }
                                                     SendTaskMessage($"产品主sn:{ProductMainSN[i]}", MessageLevel.Info);
                                                 }
                                                 string woItem = item.FirstOrDefault(f => f.Contains("wo="));
@@ -2358,6 +2366,8 @@ namespace TeamAAS_VP.Core
                                 // 上传本站数据
                                 else if (state == 2)
                                 {
+                                    DFC.Clear();
+
                                     //获取当前工位的配置
                                     var stationConfig = _configService.GetDeviceInfo(i);
                                     SendTaskMessage($"收到{i}:{stationConfig.DeviceName}上传本站数据请求...", MessageLevel.Debug);
@@ -2381,7 +2391,7 @@ namespace TeamAAS_VP.Core
                                     assemblyRecord.AssemblyDurationSeconds = ct;
                                     assemblyRecord.AssemblyPressure = pressure;
                                     assemblyRecord.DeviceId = i;
-                                    assemblyRecord.DeviceName = $"";
+                                    assemblyRecord.DeviceName = stationConfig.DeviceName;
                                     assemblyRecord.OperatorName = _systemDatabaseService.GetCurrentUser().UserName;
                                     assemblyRecord.Success = resultIndex == 1 ? true : false;
                                     assemblyRecord.DownCameraCoord1 = "";
@@ -2454,33 +2464,53 @@ namespace TeamAAS_VP.Core
                                         //判断锁付路径字符串是否为空,如果不为空则保存,否则不保存
                                         if (!string.IsNullOrEmpty(stationConfig.SaveCsvPath))
                                         {
-                                            var cdata = _configService.GetCTQDataInfo();//获取ctq数据参数
                                             bool assyPress = resultIndex == 1 ? true : false;
+                                            var pre = FileHelper.ReadJsonFile<PressureModel>(FilePath.PressureParamterConfigPath);
                                             DFC.Clear();
                                             DFC.Add(new DataFormCtq
                                             {
                                                 PPID = ProductMainSN[i],
-                                                PROCESS_NAME = cdata.PROCESS_NAME,
-                                                PROCESS_START_TIME = StartCtqTime.ToString(),
+                                                PROCESS_NAME = stationConfig.DataInfo.PROCESS_NAME,
+                                                PROCESS_START_TIME = _LastMesCheckTime[i].ToString(),
                                                 CTQ_NAME = "CC",
                                                 CTQ_VALUE = cc.Replace(",", ";"),
                                                 //CTQ_VALUE = 0,
-                                                CTQ_LSL = 0,
-                                                CTQ_USL = 10,
-                                                PROCESS_END_TIME = DateTime.Now.ToString(),
-                                                SUPPLIER_NAME = cdata.SUPPLIER_NAME,
-                                                COMMODITY_TYPE = cdata.COMMODITY_TYPE,
-                                                REVISION = cdata.REVISION,
+                                                CTQ_LSL = "",
+                                                CTQ_USL = "",
+                                                PROCESS_END_TIME = serverTimeResult.Now.ToString(),
+                                                SUPPLIER_NAME = stationConfig.DataInfo.SUPPLIER_NAME,
+                                                COMMODITY_TYPE = stationConfig.DataInfo.COMMODITY_TYPE,
+                                                REVISION = stationConfig.DataInfo.REVISION,
                                                 WO = wo[i],
-                                                MFG_LOT = cdata.MFG_LOT,
-                                                MFG_ASSY_LINE = cdata.MFG_ASSY_LINE,
-                                                PROCESS_OUTCOME = assyPress ? "PASS" : "FAIL",
-                                                PROCESS_MACHINE_ID = cdata.PROCESS_MACHINE_ID,
+                                                MFG_LOT = stationConfig.DataInfo.MFG_LOT,
+                                                MFG_ASSY_LINE = stationConfig.DataInfo.MFG_ASSY_LINE,
+                                                PROCESS_OUTCOME = "PASS",
+                                                PROCESS_MACHINE_ID = stationConfig.DataInfo.PROCESS_MACHINE_ID,
                                                 CTQ_UNIT_OF_MEASURE = "mm",
                                                 ERROR_MESSAGE = assyPress ? "" : "CC OOS"
                                             });
-
-                                            bool recordResult = RecordStationResult(i, DFC[0], ProductMainSN[i], serverTimeResult.Now.Subtract(_LastMesCheckTime[i]).TotalSeconds, _LastMesCheckTime[i], stationConfig.SaveCsvPath);
+                                            DFC.Add(new DataFormCtq
+                                            {
+                                                PPID = code,
+                                                PROCESS_NAME = stationConfig.DataInfo.PROCESS_NAME,
+                                                PROCESS_START_TIME = _LastMesCheckTime[i].ToString(),
+                                                CTQ_NAME = "Assy_Pressure",
+                                                CTQ_VALUE = Math.Round(double.Parse(assypress), 3).ToString(),
+                                                CTQ_LSL = pre.PressureDownLimit.ToString("F3"),
+                                                CTQ_USL = pre.PressureUpLimit.ToString("F3"),
+                                                PROCESS_END_TIME = serverTimeResult.Now.ToString(),
+                                                SUPPLIER_NAME = stationConfig.DataInfo.SUPPLIER_NAME,
+                                                COMMODITY_TYPE = stationConfig.DataInfo.COMMODITY_TYPE,
+                                                REVISION = stationConfig.DataInfo.REVISION,
+                                                WO = wo[i],
+                                                MFG_LOT = stationConfig.DataInfo.MFG_LOT,
+                                                MFG_ASSY_LINE = stationConfig.DataInfo.MFG_ASSY_LINE,
+                                                PROCESS_OUTCOME = assyPress ? "PASS" : "FAIL",
+                                                PROCESS_MACHINE_ID = stationConfig.DataInfo.PROCESS_MACHINE_ID,
+                                                CTQ_UNIT_OF_MEASURE = "kg",
+                                                ERROR_MESSAGE = assyPress ? "" : "Assy_Pressure OOS"
+                                            });
+                                            bool recordResult = RecordStationResult(i, DFC, ProductMainSN[i], serverTimeResult.Now.Subtract(_LastMesCheckTime[i]).TotalSeconds, _LastMesCheckTime[i], stationConfig.SaveCsvPath);
                                             if (recordResult)
                                             {
                                                 SendTaskMessage($"{i}:{stationConfig.DeviceName}产品记录保存成功", MessageLevel.Debug);
@@ -2880,14 +2910,14 @@ namespace TeamAAS_VP.Core
         /// 记录工位的结果,其他工位要存储的数据项按照键值对集合的形式传入,键为数据项名称,值为数据项的值
         /// </summary>
         /// <param name="stationIndex"></param>
-        /// <param name="dfc"></param>
+        /// <param name="dfcs"></param>
         /// <param name="productMainSN"></param>
         /// <param name="ct"></param>
         /// <param name="timestamp"></param>
         /// <param name="savePath"></param>
         /// <param name="isFirstEnter"></param>
         /// <returns></returns>
-        private bool RecordStationResult(int stationIndex, DataFormCtq dfc, string productMainSN, double ct, DateTime timestamp, string savePath, bool isFirstEnter = true)
+        private bool RecordStationResult(int stationIndex, IEnumerable<DataFormCtq> dfcs, string productMainSN, double ct, DateTime timestamp, string savePath, bool isFirstEnter = true)
         {
             try
             {
@@ -2925,8 +2955,15 @@ namespace TeamAAS_VP.Core
                         "MFG_ASSY_LINE,PROCESS_OUTCOME,PROCESS_MACHINE_ID,CTQ_UNIT_OF_MEASURE,ERROR_MESSAGE");
                     sb.AppendLine();
                 }
-                sb.Append($"{dfc.PPID},{dfc.PROCESS_NAME},{dfc.PROCESS_START_TIME},{dfc.CTQ_NAME},{dfc.CTQ_VALUE},{dfc.CTQ_LSL},{dfc.CTQ_USL},{dfc.PROCESS_END_TIME},{dfc.SUPPLIER_NAME},{dfc.COMMODITY_TYPE},{dfc.REVISION},{dfc.WO},{dfc.MFG_LOT},{dfc.MFG_ASSY_LINE},{dfc.PROCESS_OUTCOME},{dfc.PROCESS_MACHINE_ID},{dfc.CTQ_UNIT_OF_MEASURE},{dfc.ERROR_MESSAGE}");
-                sb.AppendLine();
+                if (dfcs == null || dfcs.Count() == 0)
+                {
+                    return false;
+                }
+                foreach (var dfc in dfcs)
+                {
+                    sb.Append($"{dfc.PPID},{dfc.PROCESS_NAME},{dfc.PROCESS_START_TIME},{dfc.CTQ_NAME},{dfc.CTQ_VALUE},{dfc.CTQ_LSL},{dfc.CTQ_USL},{dfc.PROCESS_END_TIME},{dfc.SUPPLIER_NAME},{dfc.COMMODITY_TYPE},{dfc.REVISION},{dfc.WO},{dfc.MFG_LOT},{dfc.MFG_ASSY_LINE},{dfc.PROCESS_OUTCOME},{dfc.PROCESS_MACHINE_ID},{dfc.CTQ_UNIT_OF_MEASURE},{dfc.ERROR_MESSAGE}");
+                    sb.AppendLine();
+                }
                 // 使用 StreamWriter 以追加模式打开文件
                 StreamWriter sw = new StreamWriter(fullPath, true, Encoding.UTF8);
                 sw.Write(sb.ToString());
@@ -2946,7 +2983,7 @@ namespace TeamAAS_VP.Core
                 string datePath = timestamp.ToString("yyyy-MM") + "\\";
                 string tempDirPath = Path.Combine(savePath, datePath, $"{stationIndex}_{timestamp.ToString("yyyy-MM-dd")}_temp");
                 string tempFileName = $"{stationIndex}_{timestamp.ToString("yyyy-MM-dd_HH-mm-ss-fff")}_temp.csv";
-                RecordStationResult(stationIndex, dfc, productMainSN, ct, timestamp, tempFileName, false);
+                RecordStationResult(stationIndex, dfcs, productMainSN, ct, timestamp, tempFileName, false);
                 return false;
             }
         }

+ 0 - 3
TeamAAS-VM/Interfaces/IConfigService.cs

@@ -533,8 +533,5 @@ namespace TeamAAS_VP.Interfaces
         /// </summary>
         /// <param name="config"></param>
         void SaveCardReaderConfig(SerialPortConfig config);
-
-        CTQ_Data GetCTQDataInfo();
-        void SaveCTQDataInfo(CTQ_Data cd);
     }
 }

+ 2 - 2
TeamAAS-VM/Interfaces/IRemoteCommandService.cs

@@ -239,7 +239,7 @@ namespace TeamAAS_VP.Interfaces
         /// <param name="InputTerminal"></param>
         /// <param name="outputCollection"></param>
         /// <returns></returns>
-        bool ExecutePhoto(ProcedureModel procedure, Dictionary<string, string> InputTerminal, out CogToolBlockTerminalCollection outputCollection);
+        bool ExecutePhoto(int index, ProcedureModel procedure, Dictionary<string, string> InputTerminal, out CogToolBlockTerminalCollection outputCollection);
 
         /// <summary>
         /// 执行相机拍照获取单个点位结果
@@ -348,7 +348,7 @@ namespace TeamAAS_VP.Interfaces
         /// <summary>
         /// 获取复检结果
         /// </summary>
-        Task<(bool IsSucceed, string distance)> ExecutePhotoGetDistance(ProcedureModel procedure, Dictionary<string, string> InputTerminal, double[] robotCoord, CancellationToken cancellationToken, int positionIndex, string remark);
+        Task<(bool IsSucceed, string distance)> ExecutePhotoGetDistance(int index, ProcedureModel procedure, Dictionary<string, string> InputTerminal, double[] robotCoord, CancellationToken cancellationToken, int positionIndex, string remark);
 
     }
 }

+ 47 - 0
TeamAAS-VM/Models/CTQ_Data.cs

@@ -129,5 +129,52 @@ namespace TeamAAS_VP.Models
         /// </summary>
         public string ERROR_MESSAGE { get => _ERROR_MESSAGE; set => SetProperty(ref _ERROR_MESSAGE, value); }
 
+        public CTQ_Data()
+        {
+            PPID = string.Empty;
+            PROCESS_NAME = string.Empty;
+            PROCESS_START_TIME = string.Empty;
+            CTQ_NAME = string.Empty;
+            CTQ_VALUE = 0.0;
+            //CTQ_LSL_Pressure = 0.0;
+            //CTQ_USL_Pressure = 0.0;
+            PROCESS_END_TIME = string.Empty;
+            SUPPLIER_NAME = string.Empty;
+            COMMODITY_TYPE = string.Empty;
+            REVISION = string.Empty;
+            WO = string.Empty;
+            MFG_LOT = string.Empty;
+            MFG_ASSY_LINE = string.Empty;
+            PROCESS_OUTCOME = string.Empty;
+            PROCESS_MACHINE_ID = string.Empty;
+            CTQ_UNIT_OF_MEASURE = string.Empty;
+            ERROR_MESSAGE = string.Empty;
+        }
+
+        public CTQ_Data Copy()
+        {
+            return new CTQ_Data
+            {
+                PPID = this.PPID,
+                PROCESS_NAME = this.PROCESS_NAME,
+                PROCESS_START_TIME = this.PROCESS_START_TIME,
+                CTQ_NAME = this.CTQ_NAME,
+                CTQ_VALUE = this.CTQ_VALUE,
+                //CTQ_LSL_Pressure = this.CTQ_LSL_Pressure,
+                //CTQ_USL_Pressure = this.CTQ_USL_Pressure,
+                PROCESS_END_TIME = this.PROCESS_END_TIME,
+                SUPPLIER_NAME = this.SUPPLIER_NAME,
+                COMMODITY_TYPE = this.COMMODITY_TYPE,
+                REVISION = this.REVISION,
+                WO = this.WO,
+                MFG_LOT = this.MFG_LOT,
+                MFG_ASSY_LINE = this.MFG_ASSY_LINE,
+                PROCESS_OUTCOME = this.PROCESS_OUTCOME,
+                PROCESS_MACHINE_ID = this.PROCESS_MACHINE_ID,
+                CTQ_UNIT_OF_MEASURE = this.CTQ_UNIT_OF_MEASURE,
+                ERROR_MESSAGE = this.ERROR_MESSAGE
+            };
+        }
+
     }
 }

+ 4 - 4
TeamAAS-VM/Models/DataFormCtq.cs

@@ -39,17 +39,17 @@ namespace TeamAAS_VP.Models
         /// </summary>
         public string CTQ_VALUE { get => _CTQ_VALUE; set => SetProperty(ref _CTQ_VALUE, value); }
 
-        private double _CTQ_LSL;
+        private string _CTQ_LSL;
         /// <summary>
         /// 下限
         /// </summary>
-        public double CTQ_LSL { get => _CTQ_LSL; set => SetProperty(ref _CTQ_LSL, value); }
+        public string CTQ_LSL { get => _CTQ_LSL; set => SetProperty(ref _CTQ_LSL, value); }
 
-        private double _CTQ_USL;
+        private string _CTQ_USL;
         /// <summary>
         /// 上限
         /// </summary>
-        public double CTQ_USL { get => _CTQ_USL; set => SetProperty(ref _CTQ_USL, value); }
+        public string CTQ_USL { get => _CTQ_USL; set => SetProperty(ref _CTQ_USL, value); }
 
         private string _PROCESS_END_TIME;
         /// <summary>

+ 10 - 3
TeamAAS-VM/Models/DeviceInfo.cs

@@ -90,6 +90,12 @@ namespace TeamAAS_VP.Models
         /// </summary>
         public bool EnableDoubleMes { get => _enableDoubleMes; set => SetProperty(ref _enableDoubleMes, value); }
 
+        private CTQ_Data _dataInfo = new CTQ_Data();
+        public CTQ_Data DataInfo
+        {
+            get { return _dataInfo; }
+            set { SetProperty(ref _dataInfo, value); }
+        }
 
         public DeviceInfo()
         {
@@ -113,13 +119,14 @@ namespace TeamAAS_VP.Models
                 Line = this.Line,
                 Station = this.Station,
                 FixtureId = this.FixtureId,
-                EnableMES = this.EnableMES,
-                MesUrl = this.MesUrl,
                 F = this.F,
                 comp = this.comp,
+                MesUrl = this.MesUrl,
+                EnableMES = this.EnableMES,
                 SaveCsv = this.SaveCsv,
                 SaveCsvPath = this.SaveCsvPath,
-                EnableDoubleMes = this.EnableDoubleMes
+                EnableDoubleMes = this.EnableDoubleMes,
+                DataInfo = this.DataInfo.Copy()
             };
         }
     }

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

@@ -284,6 +284,17 @@ namespace TeamAAS_VP.Models
             set { SetProperty(ref _SavePath, value); }
         }
 
+        //用户定义的图片文件名格式,例如:{ProductSN}_Daisy_KB Screw _01 _{CameraName}-Locate_{ShotCount}_WhiteRingLight_{Result}_{DateTime:yyyy-MM-dd_HH-mm-ss}.png
+        private string _ImageFileNameFormat;
+        /// <summary>
+        /// 用户定义的图片文件名格式,例如:{ProductSN}_Daisy_KB Screw _01 _{CameraName}-Locate_{ShotCount}_WhiteRingLight_{Result}_{DateTime:yyyy-MM-dd_HH-mm-ss}.png
+        /// </summary>
+        public string ImageFileNameFormat
+        {
+            get { return _ImageFileNameFormat; }
+            set { SetProperty(ref _ImageFileNameFormat, value); }
+        }
+
         private bool _IsCompress;
         /// <summary>
         /// 是否压缩图片
@@ -408,6 +419,7 @@ namespace TeamAAS_VP.Models
                 SaveImageModel = this.SaveImageModel,
                 SaveImagePathModel = this.SaveImagePathModel,
                 SavePath = this.SavePath,
+                ImageFileNameFormat=this.ImageFileNameFormat,
                 IsCompress = this.IsCompress,
                 FeederFindFrequency = this.FeederFindFrequency?.Copy(),
                 IsExcludeNearPoint=this.IsExcludeNearPoint,

+ 11 - 11
TeamAAS-VM/Models/ShowRender.cs

@@ -101,6 +101,17 @@ namespace TeamAAS_VP.Models
             set { SetProperty(ref _SavePath, value); }
         }
 
+        //用户定义的图片文件名
+        private string _ImageFileName;
+        /// <summary>
+        /// 用户定义的图片文件名
+        /// </summary>
+        public string ImageFileName
+        {
+            get { return _ImageFileName; }
+            set { SetProperty(ref _ImageFileName, value); }
+        }
+
         private bool _IsCompress;
         /// <summary>
         /// 是否压缩图片
@@ -111,15 +122,6 @@ namespace TeamAAS_VP.Models
             set { SetProperty(ref _IsCompress, value); }
         }
 
-        private ProductModel _CurrentProduct;
-
-        public ProductModel CurrentProduct
-        {
-            get { return _CurrentProduct; }
-            set { _CurrentProduct = value; }
-        }
-
-
         private string _ProceductName;
 
         public string ProceductName
@@ -127,7 +129,5 @@ namespace TeamAAS_VP.Models
             get { return _ProceductName; }
             set { _ProceductName = value; }
         }
-
-
     }
 }

+ 2 - 2
TeamAAS-VM/Properties/AssemblyInfo.cs

@@ -51,5 +51,5 @@ using System.Windows;
 //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
 //通过使用 "*",如下所示:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.2.1.4")]
-[assembly: AssemblyFileVersion("1.2.1.4")]
+[assembly: AssemblyVersion("1.2.1.5")]
+[assembly: AssemblyFileVersion("1.2.1.5")]

+ 0 - 47
TeamAAS-VM/Services/ConfigService.cs

@@ -71,7 +71,6 @@ namespace TeamAAS_VP.Services
         // Device info - 支持多设备
         private List<DeviceInfo> _deviceInfoList;
 
-        public CTQ_Data CtqData { get; set; }
         private PlcAddressConfig PlcAddressConfig { get; set; }
         // 单个电批配置
         private TeamAAS_VP.Models.ScrewDriver.ScrewDriverConfig _screwDriverConfig;
@@ -261,14 +260,6 @@ namespace TeamAAS_VP.Services
                     _cardReaderConfig = new SerialPortConfig();
                     FileHelper.WriteJsonFile(_cardReaderConfig, ConfigPaths.CardReaderConfigurationPath);
                 }
-
-                if (File.Exists(ConfigPaths.DataConfigurationPath))
-                    CtqData = FileHelper.ReadJsonFile<CTQ_Data>(ConfigPaths.DataConfigurationPath);
-                else
-                {
-                    CtqData = new CTQ_Data();
-                    FileHelper.WriteJsonFile(CtqData, ConfigPaths.DataConfigurationPath);
-                }
             }
         }
 
@@ -311,8 +302,6 @@ namespace TeamAAS_VP.Services
                 // save card reader config
                 if (_cardReaderConfig != null)
                     FileHelper.WriteJsonFile(_cardReaderConfig, ConfigPaths.CardReaderConfigurationPath);
-                if (CtqData != null)
-                    FileHelper.WriteJsonFile(CtqData, ConfigPaths.DataConfigurationPath);
             }
         }
 
@@ -573,42 +562,6 @@ namespace TeamAAS_VP.Services
         }
         #endregion
 
-        #region CTQData
-        /// <summary>
-        /// 获取CTQ信息配置
-        /// </summary>
-        public CTQ_Data GetCTQDataInfo()
-        {
-            lock (_sync)
-            {
-                if (CtqData == null)
-                {
-                    if (File.Exists(ConfigPaths.DataConfigurationPath))
-                        CtqData = FileHelper.ReadJsonFile<CTQ_Data>(ConfigPaths.DataConfigurationPath);
-                    else
-                    {
-                        CtqData = new CTQ_Data();
-                        FileHelper.WriteJsonFile(CtqData, ConfigPaths.DataConfigurationPath);
-                    }
-                }
-                return CtqData;
-            }
-        }
-
-        /// <summary>
-        /// 保存CTQ信息
-        /// </summary>
-        public void SaveCTQDataInfo(CTQ_Data cd)
-        {
-            if (cd == null) return;
-            lock (_sync)
-            {
-                CtqData = cd;
-                FileHelper.WriteJsonFile(CtqData, ConfigPaths.DataConfigurationPath);
-            }
-        }
-        #endregion
-
         #region Robots
         /// <summary>
         /// 获取所有机器人配置的只读集合。

+ 55 - 15
TeamAAS-VM/Services/RemoteCommandService.cs

@@ -1185,7 +1185,7 @@ namespace TeamAAS_VP.Services
                 SendTaskMessage(Lang.开始执行视觉流程.Replace("{0}", $"{i + 1}").Replace("{1}", procedure.Name), MessageLevel.Info);
 
                 // 1. 执行相机拍照并运行视觉工具
-                bool visionSucceed = ExecutePhoto(procedure, InputTerminal, out CogToolBlockTerminalCollection outputCollection);
+                bool visionSucceed = ExecutePhoto(i + 1, procedure, InputTerminal, out CogToolBlockTerminalCollection outputCollection);
                 if (!visionSucceed)
                 {
                     SendTaskMessage(Lang.视觉任务执行失败, MessageLevel.Error);
@@ -1374,7 +1374,7 @@ namespace TeamAAS_VP.Services
                     }
                     // 1. 执行相机拍照并运行视觉工具
                     LogHelper.WriteLogInfo("开始执行相机拍照并运行视觉工具");
-                    bool visionSucceed = ExecutePhoto(procedure, InputTerminal, out CogToolBlockTerminalCollection outputCollection);
+                    bool visionSucceed = ExecutePhoto(i + 1, procedure, InputTerminal, out CogToolBlockTerminalCollection outputCollection);
                     if (!visionSucceed)
                     {
                         SendTaskMessage(Lang.视觉任务执行失败, MessageLevel.Error);
@@ -1452,7 +1452,7 @@ namespace TeamAAS_VP.Services
         /// 执行相机拍照并运行 ToolBlock,返回是否成功并通过 out 参数返回 Outputs。
         /// 该方法会发布 RenderUpdateNotification 以更新 UI。
         /// </summary>
-        public bool ExecutePhoto(ProcedureModel procedure, Dictionary<string, string> InputTerminal, out CogToolBlockTerminalCollection outputCollection)
+        public bool ExecutePhoto(int index, ProcedureModel procedure, Dictionary<string, string> InputTerminal, out CogToolBlockTerminalCollection outputCollection)
         {
             try
             {
@@ -1516,20 +1516,41 @@ namespace TeamAAS_VP.Services
                         if (item.Value is ICogRecord)
                             record = item.Value as ICogRecord;
                     }
+
+                    bool Found = (bool)(outputCollection["Found"].Value);
+                    //获取图片存储的图片文件名
+                    string imgName = string.Empty;
+                    if (procedure.IsSaveImage && !string.IsNullOrEmpty(procedure.ImageFileNameFormat))
+                    {
+                        // 创建模板,使用 {变量名:格式} 语法
+                        var template = new FileNameTemplate(procedure.ImageFileNameFormat);
+
+                        // 注册变量
+                        template.RegisterVariable("ProductSN", () => _productService.CurrentProductCode);
+                        template.RegisterVariable("CameraName", () => procedure.CameraName);
+                        template.RegisterVariable("ShotCount", () => index);
+                        template.RegisterVariable("Result", () => Found ? "OK" : "NG");
+                        template.RegisterVariable("DateTime", () => DateTime.Now);
+
+                        // 生成文件名
+                        imgName = template.Generate();
+                    }
+
                     _eventAggregator.GetEvent<RenderUpdateNotification>().Publish(new ShowRender()
                     {
                         Id = procedure.Id,
                         Image = (ICogImage)procedure.ToolBlock.Inputs["InputImage"].Value,
                         Graphic = outputCollection["Graphic"].Value as CogGraphicCollection,
                         Record = record,
-                        Result = (bool)(outputCollection["Found"].Value),
+                        Result = Found,
                         IsShow = true,
                         IsSaveImage = procedure.IsSaveImage,
                         SaveImageModel = procedure.SaveImageModel,
                         SaveImagePathModel = procedure.SaveImagePathModel,
                         SavePath = procedure.SavePath,
                         IsCompress = procedure.IsCompress,
-                        ProceductName = procedure.Name
+                        ProceductName = procedure.Name,
+                        ImageFileName = imgName
                     });
                     return true;
                 }
@@ -1538,6 +1559,24 @@ namespace TeamAAS_VP.Services
                     SendTaskMessage(Lang.视觉流程执行出错耗时.Replace("{0}", procedure.Name).Replace("{1}", $"{procedure.ToolBlock.RunStatus.ProcessingTime:F1}"), MessageLevel.Error);
                     SendTaskMessage(procedure.ToolBlock.RunStatus.Message, MessageLevel.Error);
                     outputCollection = null;
+
+                    //获取图片存储的图片文件名
+                    string imgName = string.Empty;
+                    if (procedure.IsSaveImage && !string.IsNullOrEmpty(procedure.ImageFileNameFormat))
+                    {
+                        // 创建模板,使用 {变量名:格式} 语法
+                        var template = new FileNameTemplate(procedure.ImageFileNameFormat);
+
+                        // 注册变量
+                        template.RegisterVariable("ProductSN", () => _productService.CurrentProductCode);
+                        template.RegisterVariable("CameraName", () => procedure.CameraName);
+                        template.RegisterVariable("ShotCount", () => index);
+                        template.RegisterVariable("Result", () => "NG");
+                        template.RegisterVariable("DateTime", () => DateTime.Now);
+
+                        // 生成文件名
+                        imgName = template.Generate();
+                    }
                     _eventAggregator.GetEvent<RenderUpdateNotification>().Publish(new ShowRender()
                     {
                         Id = procedure.Id,
@@ -1550,6 +1589,7 @@ namespace TeamAAS_VP.Services
                         SaveImagePathModel = procedure.SaveImagePathModel,
                         SavePath = procedure.SavePath,
                         ProceductName = procedure.Name,
+                        ImageFileName = imgName
                     });
                     return false;
                 }
@@ -1572,13 +1612,13 @@ namespace TeamAAS_VP.Services
         /// <param name="outImage"></param>
         /// <param name="outGraphicCollection"></param>
         /// <returns></returns>
-        public bool ExecutePhotoEx(ProcedureModel procedure, Dictionary<string, string> InputTerminal, out CogToolBlockTerminalCollection outputCollection,out ICogImage outImage,out CogGraphicCollection outGraphicCollection)
+        public bool ExecutePhotoEx(int index, ProcedureModel procedure, Dictionary<string, string> InputTerminal, out CogToolBlockTerminalCollection outputCollection, out ICogImage outImage, out CogGraphicCollection outGraphicCollection)
         {
             outImage = null;
             outGraphicCollection = null;
             try
             {
-                
+
                 // 1. 采集图像
                 var camera = _cameraService.GetCamera(procedure.CameraId);
                 bool succed = camera.SetExposureTime(procedure.ExposureTime);
@@ -1601,7 +1641,7 @@ namespace TeamAAS_VP.Services
                     outputCollection = null;
                     return false;
                 }
-                outImage= image;
+                outImage = image;
                 procedure.ToolBlock.Inputs["InputImage"].Value = image;
                 LogHelper.WriteLogInfo($"采集图像完成;用时:{(DateTime.Now - nowtime).Milliseconds}ms");
 
@@ -1639,7 +1679,7 @@ namespace TeamAAS_VP.Services
                         if (item.Value is ICogRecord)
                             record = item.Value as ICogRecord;
                     }
-                    outGraphicCollection= outputCollection["Graphic"].Value as CogGraphicCollection;
+                    outGraphicCollection = outputCollection["Graphic"].Value as CogGraphicCollection;
                     return true;
                 }
                 else
@@ -1682,7 +1722,7 @@ namespace TeamAAS_VP.Services
                     SendTaskMessage(Lang.开始执行视觉流程.Replace("{0}", $"{i + 1}").Replace("{1}", procedure.Name), MessageLevel.Info);
 
                     // 1. 执行相机拍照并运行视觉工具
-                    bool visionSucceed = ExecutePhoto(procedure, InputTerminal, out CogToolBlockTerminalCollection outputCollection);
+                    bool visionSucceed = ExecutePhoto(i + 1, procedure, InputTerminal, out CogToolBlockTerminalCollection outputCollection);
                     if (!visionSucceed)
                     {
                         SendTaskMessage(Lang.视觉任务执行失败, MessageLevel.Error);
@@ -1768,7 +1808,7 @@ namespace TeamAAS_VP.Services
         /// <param name="positionIndex"></param>
         /// <param name="remark"></param>
         /// <returns></returns>
-        public async Task<(bool IsSucceed, string distance)> ExecutePhotoGetDistance(ProcedureModel procedure, Dictionary<string, string> InputTerminal, double[] robotCoord, CancellationToken cancellationToken, int positionIndex, string remark)
+        public async Task<(bool IsSucceed, string distance)> ExecutePhotoGetDistance(int index, ProcedureModel procedure, Dictionary<string, string> InputTerminal, double[] robotCoord, CancellationToken cancellationToken, int positionIndex, string remark)
         {
             DateTime nowtime = DateTime.Now;
             await SetLightBeforePhoto(procedure);
@@ -1780,7 +1820,7 @@ namespace TeamAAS_VP.Services
                     SendTaskMessage(Lang.开始执行视觉流程.Replace("{0}", $"{i + 1}").Replace("{1}", procedure.Name), MessageLevel.Info);
 
                     // 1. 执行相机拍照并运行视觉工具
-                    bool visionSucceed = ExecutePhoto(procedure, InputTerminal, out CogToolBlockTerminalCollection outputCollection);
+                    bool visionSucceed = ExecutePhoto(i + 1, procedure, InputTerminal, out CogToolBlockTerminalCollection outputCollection);
                     if (!visionSucceed)
                     {
                         SendTaskMessage(Lang.视觉任务执行失败, MessageLevel.Error);
@@ -1906,8 +1946,8 @@ namespace TeamAAS_VP.Services
         {
             DateTime nowtime = DateTime.Now;
             await SetLightBeforePhoto(procedure);
-            ICogImage outImage=null;
-            CogGraphicCollection outGraphicCollection=null;
+            ICogImage outImage = null;
+            CogGraphicCollection outGraphicCollection = null;
             try
             {
                 //拍照失败时,需要多次拍照
@@ -1917,7 +1957,7 @@ namespace TeamAAS_VP.Services
 
 
                     // 1. 执行相机拍照并运行视觉工具
-                    bool visionSucceed = ExecutePhotoEx(procedure, InputTerminal, out CogToolBlockTerminalCollection outputCollection, out outImage, out outGraphicCollection);
+                    bool visionSucceed = ExecutePhotoEx(i + 1, procedure, InputTerminal, out CogToolBlockTerminalCollection outputCollection, out outImage, out outGraphicCollection);
                     if (!visionSucceed)
                     {
                         SendTaskMessage(Lang.视觉任务执行失败, MessageLevel.Error);

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

@@ -532,6 +532,7 @@
     <Compile Include="Controls\PlcRobotManual.xaml.cs">
       <DependentUpon>PlcRobotManual.xaml</DependentUpon>
     </Compile>
+    <Compile Include="Core\FileNameTemplate.cs" />
     <Compile Include="Core\RectangleCenterCalculator.cs" />
     <Compile Include="Core\StabilityAnalyzer.cs" />
     <Compile Include="Core\VisionProFileHelper.cs" />
@@ -548,6 +549,7 @@
     <Compile Include="Models\ScrewFeederBatchRecord.cs" />
     <Compile Include="Services\MesService.cs" />
     <Compile Include="ValueConverter\CountToColumnsConverter.cs" />
+    <Compile Include="ValueConverter\ImageFileNameFormatConverter.cs" />
     <Compile Include="ViewModels\DebugMod\PlcRobotManualStepViewModel.cs" />
     <Compile Include="ViewModels\Product\ImageDisplayViewModel.cs" />
     <Compile Include="ViewModels\Product\PlcPointOffserParamsViewModel.cs" />

+ 43 - 0
TeamAAS-VM/ValueConverter/ImageFileNameFormatConverter.cs

@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+using TeamAAS_VP.Core;
+
+namespace TeamAAS_VP.ValueConverter
+{
+    public class ImageFileNameFormatConverter : IValueConverter
+    {
+        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+        {
+            try
+            {
+                if (value == null) return string.Empty;
+                // 创建模板,使用 {变量名:格式} 语法
+                var template = new FileNameTemplate(value.ToString());
+
+                // 注册变量
+                template.RegisterVariable("ProductSN", () => "SN12345");
+                template.RegisterVariable("CameraName", () => "MainCamera");
+                template.RegisterVariable("ShotCount", () => 3);
+                template.RegisterVariable("Result", () => "OK");
+                template.RegisterVariable("DateTime", () => DateTime.Now);
+
+                // 生成文件名
+                string fileName = template.Generate();
+                return fileName;
+            }
+            catch (Exception)
+            {
+                return value.ToString();
+            }
+        }
+
+        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+        {
+            throw new NotImplementedException();
+        }
+    }
+}

+ 1 - 6
TeamAAS-VM/ViewModels/SettingViewModel.cs

@@ -1681,12 +1681,7 @@ namespace TeamAAS_VP.ViewModels
         {
             try
             {
-                if (SelectDeviceInfo != null)
-                {
-                    _configService.SaveDeviceInfo(SelectDeviceInfo);
-                    _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = Lang.完成, Duration = 1 });
-                }
-                else if (DeviceInfoList != null && DeviceInfoList.Count > 0)
+                if (DeviceInfoList != null && DeviceInfoList.Count > 0)
                 {
                     // 保存所有设备信息
                     _configService.SaveAllDeviceInfos(DeviceInfoList);

+ 33 - 32
TeamAAS-VM/Views/Home/ShowVisionRender.xaml.cs

@@ -315,7 +315,8 @@ namespace TeamAAS_VP.Views.Home
                                 render.Image,
                                 clonedBitmap,
                                 render.Result,
-                                render.IsCompress
+                                render.IsCompress,
+                                render.ImageFileName
                             );
                         }
                         catch (OperationCanceledException)
@@ -349,13 +350,7 @@ namespace TeamAAS_VP.Views.Home
         /// <summary>
         /// 保存图像(保持你原有逻辑不变,补充 Dispose 兜底,防止压缩分支不释放导致闪退)
         /// </summary>
-        private void SaveImage(ProcedureSaveImageModel saveImageModel,
-                               ProcedureSaveImagePathModel saveImagePathModel,
-                               string path,
-                               ICogImage image,
-                               Bitmap reimage,
-                               bool result,
-                               bool isCompress)
+        private void SaveImage(ProcedureSaveImageModel saveImageModel, ProcedureSaveImagePathModel saveImagePathModel, string path, ICogImage image, Bitmap reimage, bool result, bool isCompress, string imageFileName)
         {
             if (string.IsNullOrEmpty(path) || string.IsNullOrWhiteSpace(path) || !Path.IsPathRooted(path))
             {
@@ -369,28 +364,34 @@ namespace TeamAAS_VP.Views.Home
                 try
                 {
                     DateTime now = DateTime.Now;
+                    //图片名
+                    string imgName = now.ToString("yyyy-MM-dd HH_mm_ss");
+                    if (!string.IsNullOrEmpty(imageFileName))
+                    {
+                        imgName = imageFileName;
+                    }
 
                     if (saveImageModel == ProcedureSaveImageModel.Original)
                     {
-                        string Originalpath = $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\{now:yyyy-MM-dd HH_mm_ss}.bmp";
+                        string Originalpath = $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.bmp";
 
                         if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_OkNG_Time)
                         {
                             Originalpath = result
-                                ? $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{now:yyyy-MM-dd HH_mm_ss}.bmp"
-                                : $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{now:yyyy-MM-dd HH_mm_ss}.bmp";
+                                ? $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp"
+                                : $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
                         }
                         else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ok_Time)
                         {
                             if (result)
-                                Originalpath = $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{now:yyyy-MM-dd HH_mm_ss}.bmp";
+                                Originalpath = $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp";
                             else
                                 return;
                         }
                         else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ng_Time)
                         {
                             if (!result)
-                                Originalpath = $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{now:yyyy-MM-dd HH_mm_ss}.bmp";
+                                Originalpath = $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
                             else
                                 return;
                         }
@@ -407,7 +408,7 @@ namespace TeamAAS_VP.Views.Home
                                 productSN = productSN.Replace(c, '_');
 
                             string resultStr = result ? "OK" : "NG";
-                            Originalpath = $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{productSN}-{now:yyyy-MM-dd HH_mm_ss}-{resultStr}.bmp";
+                            Originalpath = $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{imgName}.bmp";
                         }
 
                         if (!Directory.Exists(Path.GetDirectoryName(Originalpath)))
@@ -422,25 +423,25 @@ namespace TeamAAS_VP.Views.Home
                     }
                     else if (saveImageModel == ProcedureSaveImageModel.Recorded)
                     {
-                        string Recordedpath = $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\{now:yyyy-MM-dd HH_mm_ss}.bmp";
+                        string Recordedpath = $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.bmp";
 
                         if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_OkNG_Time)
                         {
                             Recordedpath = result
-                                ? $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{now:yyyy-MM-dd HH_mm_ss}.bmp"
-                                : $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{now:yyyy-MM-dd HH_mm_ss}.bmp";
+                                ? $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp"
+                                : $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
                         }
                         else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ok_Time)
                         {
                             if (result)
-                                Recordedpath = $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{now:yyyy-MM-dd HH_mm_ss}.bmp";
+                                Recordedpath = $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp";
                             else
                                 return;
                         }
                         else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ng_Time)
                         {
                             if (!result)
-                                Recordedpath = $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{now:yyyy-MM-dd HH_mm_ss}.bmp";
+                                Recordedpath = $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
                             else
                                 return;
                         }
@@ -455,7 +456,7 @@ namespace TeamAAS_VP.Views.Home
                                 productSN = productSN.Replace(c, '_');
 
                             string resultStr = result ? "OK" : "NG";
-                            Recordedpath = $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{productSN}-{now:yyyy-MM-dd HH_mm_ss}-{resultStr}.bmp";
+                            Recordedpath = $"{path}\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{imgName}.bmp";
                         }
 
                         if (!Directory.Exists(Path.GetDirectoryName(Recordedpath)))
@@ -472,28 +473,28 @@ namespace TeamAAS_VP.Views.Home
                     }
                     else if (saveImageModel == ProcedureSaveImageModel.OriginalAndRecorded)
                     {
-                        string Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{now:yyyy-MM-dd HH_mm_ss}.bmp";
-                        string Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\{now:yyyy-MM-dd HH_mm_ss}.bmp";
+                        string Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.bmp";
+                        string Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\{imgName}.bmp";
 
                         if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_OkNG_Time)
                         {
                             if (result)
                             {
-                                Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{now:yyyy-MM-dd HH_mm_ss}.bmp";
-                                Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{now:yyyy-MM-dd HH_mm_ss}.bmp";
+                                Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp";
+                                Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp";
                             }
                             else
                             {
-                                Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{now:yyyy-MM-dd HH_mm_ss}.bmp";
-                                Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{now:yyyy-MM-dd HH_mm_ss}.bmp";
+                                Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
+                                Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
                             }
                         }
                         else if (saveImagePathModel == ProcedureSaveImagePathModel.Month_Day_Ok_Time)
                         {
                             if (result)
                             {
-                                Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{now:yyyy-MM-dd HH_mm_ss}.bmp";
-                                Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{now:yyyy-MM-dd HH_mm_ss}.bmp";
+                                Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp";
+                                Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\OK\\{imgName}.bmp";
                             }
                             else
                             {
@@ -504,8 +505,8 @@ namespace TeamAAS_VP.Views.Home
                         {
                             if (!result)
                             {
-                                Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{now:yyyy-MM-dd HH_mm_ss}.bmp";
-                                Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{now:yyyy-MM-dd HH_mm_ss}.bmp";
+                                Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
+                                Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\NG\\{imgName}.bmp";
                             }
                             else
                             {
@@ -523,8 +524,8 @@ namespace TeamAAS_VP.Views.Home
                                 productSN = productSN.Replace(c, '_');
 
                             string resultStr = result ? "OK" : "NG";
-                            Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{productSN}-{now:yyyy-MM-dd HH_mm_ss}-{resultStr}.bmp";
-                            Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{productSN}-{now:yyyy-MM-dd HH_mm_ss}-{resultStr}.bmp";
+                            Originalpath = $"{path}\\Original\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{imgName}.bmp";
+                            Recordedpath = $"{path}\\Recored\\{now:yyyy-MM}\\{now:MM-dd}\\{formulaName}\\{productSN}\\{resultStr}\\{imgName}.bmp";
                         }
 
                         if (!Directory.Exists(Path.GetDirectoryName(Originalpath)))

+ 47 - 10
TeamAAS-VM/Views/Product/ProcedureParams.xaml

@@ -20,7 +20,7 @@
              prism:ViewModelLocator.AutoWireViewModel="True"
              mc:Ignorable="d"
              d:DataContext="{d:DesignInstance Type=vm:ProcedureParamsViewModel}"
-             d:Height="600"
+             d:Height="1080"
              d:Width="1024"
              d:Background="White"
              FontFamily="{DynamicResource DefaultFont}">
@@ -30,7 +30,7 @@
         </b:EventTrigger>
     </b:Interaction.Triggers>
     <UserControl.Resources>
-
+        <valueConverter:ImageFileNameFormatConverter x:Key="ImageFileNameFormatConverter" />
     </UserControl.Resources>
     <Grid>
         <Grid.RowDefinitions>
@@ -107,7 +107,8 @@
             </Expander>
             <ScrollViewer Grid.Column="1"
                           IsEnabled="{Binding IsAllowEdit}">
-                <Grid Grid.Column="1"
+                <Grid x:Name="grid"
+                      Grid.Column="1"
                       Margin="10"
                       IsEnabled="{Binding IsAllowEdit}"
                       HorizontalAlignment="Center"
@@ -132,6 +133,8 @@
                         <RowDefinition Height="auto" />
                         <RowDefinition Height="auto" />
                         <RowDefinition Height="auto" />
+                        <RowDefinition Height="auto" />
+                        <RowDefinition Height="auto" />
                     </Grid.RowDefinitions>
                     <Grid.ColumnDefinitions>
                         <ColumnDefinition Width="auto" />
@@ -428,8 +431,42 @@
                               Visibility="{Binding ElementName=chbSaveImage,Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}"
                               IsChecked="{Binding SelectProcedure.IsCompress,Mode=TwoWay}"
                               Style="{StaticResource MaterialDesignLightCheckBox}" />
+                    <!--图片名称格式-->
+                    <TextBlock Grid.Row="14"
+                               Grid.Column="0"
+                               Visibility="{Binding ElementName=chbSaveImage,Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}"
+                               Text="图片名称格式:" />
+                    <TextBox Grid.Row="14"
+                             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="15"
+                                Grid.Column="0"
+                                Grid.ColumnSpan="2"
+                                Orientation="Vertical"
+                                Visibility="{Binding ElementName=chbSaveImage,Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}">
+                        <TextBlock Text="示例:{ProductSN}_Daisy_KB Screw _01 _{CameraName}-Locate_{ShotCount}_WhiteRingLight_{Result}_{DateTime:yyyy-MM-dd_HH-mm-ss}"
+                                   Foreground="LightGray"
+                                   FontSize="10"
+                                   TextTrimming="CharacterEllipsis"
+                                   TextWrapping="Wrap"
+                                   Width="{Binding Width, ElementName=grid}" />
+                        <TextBlock Text="转换后的名称:"
+                                   Foreground="Gray"
+                                   FontSize="10" />
+                        <TextBlock Text="{Binding SelectProcedure.ImageFileNameFormat,Converter={StaticResource ImageFileNameFormatConverter},Mode=TwoWay}"
+                                   Foreground="Gray"
+                                   FontSize="10"
+                                   TextTrimming="CharacterEllipsis"
+                                   TextWrapping="Wrap"
+                                   Width="{Binding Width, ElementName=grid}"  />
+                    </StackPanel>
+
                     <!--自定义参数-->
-                    <GroupBox Grid.Row="14"
+                    <GroupBox Grid.Row="16"
                               Grid.Column="0"
                               Grid.ColumnSpan="2"
                               HorizontalAlignment="Stretch"
@@ -440,12 +477,12 @@
                             <StackPanel DockPanel.Dock="Top"
                                         Orientation="Horizontal">
                                 <Button Content="{materialDesign:PackIcon Kind=AddCircle}"
-                                        Style="{StaticResource MahApps.Styles.Button.Flat}" 
-                                        Command="{Binding AddUserDefineParameterCommand}"/>
+                                        Style="{StaticResource MahApps.Styles.Button.Flat}"
+                                        Command="{Binding AddUserDefineParameterCommand}" />
                                 <Button Content="{materialDesign:PackIcon Kind=RemoveCircle}"
                                         Style="{StaticResource MahApps.Styles.Button.Flat}"
-                                        Margin="5,0" 
-                                        Command="{Binding RemoveUserDefineParameterCommand}"/>
+                                        Margin="5,0"
+                                        Command="{Binding RemoveUserDefineParameterCommand}" />
                             </StackPanel>
                             <DataGrid HorizontalAlignment="Stretch"
                                       VerticalAlignment="Stretch"
@@ -499,10 +536,10 @@
                             </DataGrid>
                         </DockPanel>
                     </GroupBox>
-                    <TextBlock Grid.Row="15"
+                    <TextBlock Grid.Row="17"
                                Grid.Column="0"
                                Text="{lex:Loc 重写视觉处理逻辑}" />
-                    <Button Grid.Row="15"
+                    <Button Grid.Row="17"
                             Grid.Column="1"
                             Margin="0,2,0,0"
                             Command="{Binding OverrideVisionTaskCommand}">

+ 186 - 85
TeamAAS-VM/Views/SettingView.xaml

@@ -334,6 +334,17 @@
                                     <RowDefinition Height="Auto" />
                                     <RowDefinition Height="Auto" />
                                     <RowDefinition Height="Auto" />
+                                    <RowDefinition Height="Auto" />
+                                    <RowDefinition Height="Auto" />
+                                    <RowDefinition Height="Auto" />
+                                    <RowDefinition Height="Auto" />
+                                    <RowDefinition Height="Auto" />
+                                    <RowDefinition Height="Auto" />
+                                    <RowDefinition Height="Auto" />
+                                    <RowDefinition Height="Auto" />
+                                    <RowDefinition Height="Auto" />
+                                    <RowDefinition Height="Auto" />
+                                    <RowDefinition Height="Auto" />
                                 </Grid.RowDefinitions>
                                 <Grid.ColumnDefinitions>
                                     <ColumnDefinition Width="auto" />
@@ -470,7 +481,96 @@
                                     <TextBox  Text="{Binding SelectDeviceInfo.SaveCsvPath, Mode=TwoWay}" />
 
                                 </DockPanel>
+                                <!--CTQ 数据信息-->
+                                <TextBlock Grid.Row="13"
+                                           Grid.Column="0"
+                                           Text="PROCESS_NAME:"
+                                           HorizontalAlignment="Right"
+                                           VerticalAlignment="Center" />
+                                <TextBox Grid.Row="13"
+                                         Grid.Column="1"
+                                         Text="{Binding SelectDeviceInfo.DataInfo.PROCESS_NAME, Mode=TwoWay}"
+                                         Margin="6,2" />
+
+                                <!--<TextBlock Grid.Row="14"
+                       Grid.Column="0"
+                       Text="CTQ_LSL(压力下限):"
+                       HorizontalAlignment="Right"
+                       VerticalAlignment="Center" />
+            <TextBox Grid.Row="14"
+                     Grid.Column="1"
+                     Text="{Binding SelectDeviceInfo.DataInfo.CTQ_LSL_Pressure, Mode=TwoWay}"
+                     Margin="6,2" />
+
+            <TextBlock Grid.Row="15"
+                       Grid.Column="0"
+                       Text="CTQ_USL(压力上限):"
+                       HorizontalAlignment="Right"
+                       VerticalAlignment="Center" />
+            <TextBox Grid.Row="15"
+                     Grid.Column="1"
+                     Text="{Binding SelectDeviceInfo.DataInfo.CTQ_USL_Pressure, Mode=TwoWay}"
+                     Margin="6,2" />-->
+
+                                <TextBlock Grid.Row="16"
+                                           Grid.Column="0"
+                                           Text="SUPPLIER_NAME:"
+                                           HorizontalAlignment="Right"
+                                           VerticalAlignment="Center" />
+                                <TextBox Grid.Row="16"
+                                         Grid.Column="1"
+                                         Text="{Binding SelectDeviceInfo.DataInfo.SUPPLIER_NAME, Mode=TwoWay}"
+                                         Margin="6,2" />
+
+                                <TextBlock Grid.Row="17"
+                                           Grid.Column="0"
+                                           Text="COMMODITY_TYPE:"
+                                           HorizontalAlignment="Right"
+                                           VerticalAlignment="Center" />
+                                <TextBox Grid.Row="17"
+                                         Grid.Column="1"
+                                         Text="{Binding SelectDeviceInfo.DataInfo.COMMODITY_TYPE, Mode=TwoWay}"
+                                         Margin="6,2" />
+
+                                <TextBlock Grid.Row="18"
+                                           Grid.Column="0"
+                                           Text="REVISION:"
+                                           HorizontalAlignment="Right"
+                                           VerticalAlignment="Center" />
+                                <TextBox Grid.Row="18"
+                                         Grid.Column="1"
+                                         Text="{Binding SelectDeviceInfo.DataInfo.REVISION, Mode=TwoWay}"
+                                         Margin="6,2" />
+
+                                <TextBlock Grid.Row="19"
+                                           Grid.Column="0"
+                                           Text="MFG_LOT#:"
+                                           HorizontalAlignment="Right"
+                                           VerticalAlignment="Center" />
+                                <TextBox Grid.Row="19"
+                                         Grid.Column="1"
+                                         Text="{Binding SelectDeviceInfo.DataInfo.MFG_LOT, Mode=TwoWay}"
+                                         Margin="6,2" />
+
+                                <TextBlock Grid.Row="20"
+                                           Grid.Column="0"
+                                           Text="MFG_ASSY_LINE:"
+                                           HorizontalAlignment="Right"
+                                           VerticalAlignment="Center" />
+                                <TextBox Grid.Row="20"
+                                         Grid.Column="1"
+                                         Text="{Binding SelectDeviceInfo.DataInfo.MFG_ASSY_LINE, Mode=TwoWay}"
+                                         Margin="6,2" />
 
+                                <TextBlock Grid.Row="21"
+                                           Grid.Column="0"
+                                           Text="PROCESS_MACHINE_ID:"
+                                           HorizontalAlignment="Right"
+                                           VerticalAlignment="Center" />
+                                <TextBox Grid.Row="21"
+                                         Grid.Column="1"
+                                         Text="{Binding SelectDeviceInfo.DataInfo.PROCESS_MACHINE_ID, Mode=TwoWay}"
+                                         Margin="6,2" />
                             </Grid>
                         </Grid>
                     </ScrollViewer>
@@ -1634,7 +1734,8 @@
                             </Grid.RowDefinitions>
                             <Grid.ColumnDefinitions>
                                 <ColumnDefinition Width="auto" />
-                                <ColumnDefinition Width="*"  MinWidth="200"/>
+                                <ColumnDefinition Width="*"
+                                                  MinWidth="200" />
                             </Grid.ColumnDefinitions>
 
                             <!-- Id -->
@@ -1784,7 +1885,7 @@
                                     <ComboBox Grid.Row="2"
                                               Grid.Column="1"
                                               SelectedItem="{Binding SelectLightController.SerialPortConfig.Parity,Mode=TwoWay}"
-                                              ItemsSource="{Binding Source={StaticResource Parity}}"/>
+                                              ItemsSource="{Binding Source={StaticResource Parity}}" />
                                     <TextBlock Text="StopBits:"
                                                Grid.Row="3"
                                                Grid.Column="0"
@@ -1951,7 +2052,7 @@
                                                        Margin="10,0,0,0" />
                                             <CheckBox IsChecked="{Binding LowLevelAlarmEnabled,Mode=TwoWay}"
                                                       IsEnabled="False"
-                                                       FontSize="{DynamicResource Font.Size.Captions3}" />
+                                                      FontSize="{DynamicResource Font.Size.Captions3}" />
                                         </StackPanel>
                                         <Border Height="2"
                                                 Margin="0"
@@ -2738,11 +2839,11 @@
                                 </Grid>
                             </GroupBox>
                             <GroupBox Grid.Row="5"
-                  Grid.ColumnSpan="2"
-                  Header="扫码机配置"
-                  HorizontalAlignment="Left"
-                  MinWidth="170"
-                  Margin="0,0,0,0">
+                                      Grid.ColumnSpan="2"
+                                      Header="扫码机配置"
+                                      HorizontalAlignment="Left"
+                                      MinWidth="170"
+                                      Margin="0,0,0,0">
                                 <Grid Margin="10">
                                     <Grid.ColumnDefinitions>
                                         <ColumnDefinition Width="auto" />
@@ -2757,45 +2858,45 @@
                                         <RowDefinition Height="Auto" />
                                     </Grid.RowDefinitions>
                                     <TextBlock Text="PortName:"
-                           Grid.Row="0"
-                           Grid.Column="0"
-                           HorizontalAlignment="Right" />
+                                               Grid.Row="0"
+                                               Grid.Column="0"
+                                               HorizontalAlignment="Right" />
                                     <TextBox Text="{Binding ScanConfig.PortName,Mode=TwoWay}"
-                         Grid.Row="0"
-                         Grid.Column="1"
-                         Margin="6,0" />
+                                             Grid.Row="0"
+                                             Grid.Column="1"
+                                             Margin="6,0" />
                                     <TextBlock Text="BaudRate:"
-                           Grid.Row="1"
-                           Grid.Column="0"
-                           HorizontalAlignment="Right" />
+                                               Grid.Row="1"
+                                               Grid.Column="0"
+                                               HorizontalAlignment="Right" />
                                     <TextBox Text="{Binding ScanConfig.BaudRate,Mode=TwoWay}"
-                         Grid.Row="1"
-                         Grid.Column="1"
-                         Margin="6,0" />
+                                             Grid.Row="1"
+                                             Grid.Column="1"
+                                             Margin="6,0" />
                                     <TextBlock Text="Parity:"
-                           Grid.Row="2"
-                           Grid.Column="0"
-                           HorizontalAlignment="Right" />
+                                               Grid.Row="2"
+                                               Grid.Column="0"
+                                               HorizontalAlignment="Right" />
                                     <ComboBox Grid.Row="2"
-                          Grid.Column="1"
-                          SelectedItem="{Binding ScanConfig.Parity,Mode=TwoWay}"
-                          ItemsSource="{Binding Source={StaticResource Parity}}" />
+                                              Grid.Column="1"
+                                              SelectedItem="{Binding ScanConfig.Parity,Mode=TwoWay}"
+                                              ItemsSource="{Binding Source={StaticResource Parity}}" />
                                     <TextBlock Text="StopBits:"
-                           Grid.Row="3"
-                           Grid.Column="0"
-                           HorizontalAlignment="Right" />
+                                               Grid.Row="3"
+                                               Grid.Column="0"
+                                               HorizontalAlignment="Right" />
                                     <ComboBox Grid.Row="3"
-                          Grid.Column="1"
-                          SelectedItem="{Binding ScanConfig.StopBits,Mode=TwoWay}"
-                          ItemsSource="{Binding Source={StaticResource StopBits}}" />
+                                              Grid.Column="1"
+                                              SelectedItem="{Binding ScanConfig.StopBits,Mode=TwoWay}"
+                                              ItemsSource="{Binding Source={StaticResource StopBits}}" />
                                     <TextBlock Text="DataBits:"
-                           Grid.Row="4"
-                           Grid.Column="0"
-                           HorizontalAlignment="Right" />
+                                               Grid.Row="4"
+                                               Grid.Column="0"
+                                               HorizontalAlignment="Right" />
                                     <TextBox Text="{Binding ScanConfig.DataBits,Mode=TwoWay}"
-                         Grid.Row="4"
-                         Grid.Column="1"
-                         Margin="6,0" />
+                                             Grid.Row="4"
+                                             Grid.Column="1"
+                                             Margin="6,0" />
 
                                     <!--<Button Grid.Row="5"
                         Grid.Column="0"
@@ -2817,8 +2918,8 @@
                             </GroupBox>
 
                             <GroupBox Header="A_Camera Assy配置"
-          Margin="20,0"
-          Width="200">
+                                      Margin="20,0"
+                                      Width="200">
                                 <Grid Margin="10">
                                     <Grid.ColumnDefinitions>
                                         <ColumnDefinition Width="auto" />
@@ -2834,65 +2935,65 @@
                                         <RowDefinition Height="Auto" />
                                     </Grid.RowDefinitions>
                                     <TextBlock Text="保压时间:"
-                   Grid.Row="0"
-                   Grid.Column="0"
-                   HorizontalAlignment="Right" />
+                                               Grid.Row="0"
+                                               Grid.Column="0"
+                                               HorizontalAlignment="Right" />
                                     <TextBox Text="{Binding DownPressureConfig.PressureTime,Mode=TwoWay}"
-                 Grid.Row="0"
-                 Grid.Column="1"
-                 Margin="6,0" />
+                                             Grid.Row="0"
+                                             Grid.Column="1"
+                                             Margin="6,0" />
                                     <TextBlock Text="ms"
-                   Grid.Row="0"
-                   Grid.Column="2"
-                   HorizontalAlignment="Right" />
+                                               Grid.Row="0"
+                                               Grid.Column="2"
+                                               HorizontalAlignment="Right" />
                                     <TextBlock Text="保压压力:"
-                   Grid.Row="1"
-                   Grid.Column="0"
-                   HorizontalAlignment="Right" />
+                                               Grid.Row="1"
+                                               Grid.Column="0"
+                                               HorizontalAlignment="Right" />
                                     <TextBox Text="{Binding DownPressureConfig.PressureNum,Mode=TwoWay}"
-                 Grid.Row="1"
-                 Grid.Column="1"
-                 Margin="6,0" />
+                                             Grid.Row="1"
+                                             Grid.Column="1"
+                                             Margin="6,0" />
                                     <TextBlock Text="kg"
-                   Grid.Row="1"
-                   Grid.Column="2"
-                   HorizontalAlignment="Right" />
+                                               Grid.Row="1"
+                                               Grid.Column="2"
+                                               HorizontalAlignment="Right" />
                                     <TextBlock Text="保压最大值:"
-                   Grid.Row="2"
-                   Grid.Column="0"
-                   HorizontalAlignment="Right" />
+                                               Grid.Row="2"
+                                               Grid.Column="0"
+                                               HorizontalAlignment="Right" />
                                     <TextBox Text="{Binding DownPressureConfig.PressureNumMax,Mode=TwoWay}"
-                 Grid.Row="2"
-                 Grid.Column="1"
-                 Margin="6,0" />
+                                             Grid.Row="2"
+                                             Grid.Column="1"
+                                             Margin="6,0" />
                                     <TextBlock Text="kg"
-                   Grid.Row="2"
-                   Grid.Column="2"
-                   HorizontalAlignment="Right" />
+                                               Grid.Row="2"
+                                               Grid.Column="2"
+                                               HorizontalAlignment="Right" />
                                     <TextBlock Text="保压上限:"
-                   Grid.Row="4"
-                   Grid.Column="0"
-                   HorizontalAlignment="Right" />
+                                               Grid.Row="4"
+                                               Grid.Column="0"
+                                               HorizontalAlignment="Right" />
                                     <TextBox Text="{Binding DownPressureConfig.PressureUpLimit,Mode=TwoWay}"
-                 Grid.Row="4"
-                 Grid.Column="1"
-                 Margin="6,0" />
+                                             Grid.Row="4"
+                                             Grid.Column="1"
+                                             Margin="6,0" />
                                     <TextBlock Text="kg"
-                   Grid.Row="4"
-                   Grid.Column="2"
-                   HorizontalAlignment="Right" />
+                                               Grid.Row="4"
+                                               Grid.Column="2"
+                                               HorizontalAlignment="Right" />
                                     <TextBlock Text="保压下限:"
-                   Grid.Row="5"
-                   Grid.Column="0"
-                   HorizontalAlignment="Right" />
+                                               Grid.Row="5"
+                                               Grid.Column="0"
+                                               HorizontalAlignment="Right" />
                                     <TextBox Text="{Binding DownPressureConfig.PressureDownLimit,Mode=TwoWay}"
-                 Grid.Row="5"
-                 Grid.Column="1"
-                 Margin="6,0" />
+                                             Grid.Row="5"
+                                             Grid.Column="1"
+                                             Margin="6,0" />
                                     <TextBlock Text="kg"
-                   Grid.Row="5"
-                   Grid.Column="2"
-                   HorizontalAlignment="Right" />
+                                               Grid.Row="5"
+                                               Grid.Column="2"
+                                               HorizontalAlignment="Right" />
                                 </Grid>
                             </GroupBox>
                         </StackPanel>