From 78584911d0457ad9fc26d9dfc6f374b7ef531c0f Mon Sep 17 00:00:00 2001
From: xcd <834800634@qq.com>
Date: 星期日, 22 十一月 2020 13:45:09 +0800
Subject: [PATCH] 1. 添加操作员输入和界面显示 2. 添加通过输入窗体 3. 添加webservice调用帮助类 4. M071添加MES数据检查和数据上传功能,添加相关界面显示和流程控制

---
 src/Bro.M071.Process/UI/M071_MainForm.cs             |   59 +++
 src/Bro.UI.Model.Winform/UI/InputWindow.resx         |  120 ++++++++
 src/Bro.Common.Model/Bro.Common.Model.csproj         |    3 
 src/Bro.M071.Process/UI/M071_MainForm.Designer.cs    |   79 ++++-
 src/Bro.UI.Model.Winform/UI/InputWindow.Designer.cs  |  108 +++++++
 src/Bro.M071.Process/M071Process_MES.cs              |  239 +++++++++++++++
 src/Bro.M071.Process/UI/M071_MainForm.resx           |    3 
 M071.sln                                             |    1 
 src/Bro.M071.Process/M071Process.cs                  |   67 +++-
 src/Bro.Common.Model/Helper/WebServiceHelper.cs      |   98 ++++++
 src/Bro.M071.Process/Bro.M071.Process.csproj         |    4 
 src/Bro.UI.Model.Winform/Bro.UI.Model.Winform.csproj |    9 
 src/Bro.M071.Process/M071Config.cs                   |   32 ++
 src/Bro.M071.Process/M071Models.cs                   |    5 
 src/Bro.M071.Process/Properties/AssemblyInfo.cs      |    4 
 src/Bro.UI.Model.Winform/UI/InputWindow.cs           |   65 ++++
 16 files changed, 856 insertions(+), 40 deletions(-)

diff --git a/M071.sln b/M071.sln
index 44b1623..c1e267a 100644
--- a/M071.sln
+++ b/M071.sln
@@ -142,6 +142,7 @@
 		{741F6491-57C7-479A-B391-09BBA9FBA9DC}.Release|x64.ActiveCfg = Release|Any CPU
 		{741F6491-57C7-479A-B391-09BBA9FBA9DC}.Release|x64.Build.0 = Release|Any CPU
 		{B536003E-70BA-4701-B8FD-BAFA303AB4E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{B536003E-70BA-4701-B8FD-BAFA303AB4E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{B536003E-70BA-4701-B8FD-BAFA303AB4E2}.Debug|x64.ActiveCfg = Debug|Any CPU
 		{B536003E-70BA-4701-B8FD-BAFA303AB4E2}.Debug|x64.Build.0 = Debug|Any CPU
 		{B536003E-70BA-4701-B8FD-BAFA303AB4E2}.Debug1|Any CPU.ActiveCfg = Debug|Any CPU
diff --git a/src/Bro.Common.Model/Bro.Common.Model.csproj b/src/Bro.Common.Model/Bro.Common.Model.csproj
index 5bb013e..74fedf2 100644
--- a/src/Bro.Common.Model/Bro.Common.Model.csproj
+++ b/src/Bro.Common.Model/Bro.Common.Model.csproj
@@ -88,6 +88,8 @@
     <Reference Include="System.Core" />
     <Reference Include="System.Design" />
     <Reference Include="System.Drawing" />
+    <Reference Include="System.Web" />
+    <Reference Include="System.Web.Services" />
     <Reference Include="System.Windows.Forms" />
     <Reference Include="System.Xml.Linq" />
     <Reference Include="System.Data.DataSetExtensions" />
@@ -130,6 +132,7 @@
     <Compile Include="Helper\TimeOutHelper.cs" />
     <Compile Include="Helper\UIHelper.cs" />
     <Compile Include="Helper\WebApiHelper.cs" />
+    <Compile Include="Helper\WebServiceHelper.cs" />
     <Compile Include="Interface\IMenuNode.cs" />
     <Compile Include="Interface\IConfigCtrl.cs" />
     <Compile Include="Interface\ICSVOutput.cs" />
diff --git a/src/Bro.Common.Model/Helper/WebServiceHelper.cs b/src/Bro.Common.Model/Helper/WebServiceHelper.cs
new file mode 100644
index 0000000..858932a
--- /dev/null
+++ b/src/Bro.Common.Model/Helper/WebServiceHelper.cs
@@ -0,0 +1,98 @@
+锘縰sing System;
+using System.CodeDom;
+using System.CodeDom.Compiler;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading.Tasks;
+using System.Web;
+using System.Web.Caching;
+using System.Web.Services.Description;
+using System.Xml.Serialization;
+
+namespace Bro.Common.Helper
+{
+    public class WebServiceHelper
+    {
+        /// <summary>
+        /// 鐢熸垚dll鏂囦欢淇濆瓨鍒版湰鍦�
+        /// </summary>
+        /// <param name="url">WebService鍦板潃</param>
+        /// <param name="className">绫诲悕</param>
+        /// <param name="methodName">鏂规硶鍚�</param>
+        /// <param name="filePath">淇濆瓨dll鏂囦欢鐨勮矾寰�</param>
+        public static void CreateWebServiceDLL(string url, string className, string methodName, string filePath)
+        {
+            // 1. 浣跨敤 WebClient 涓嬭浇 WSDL 淇℃伅銆�
+            WebClient web = new WebClient();
+            Stream stream = web.OpenRead(url + "?wsdl");
+            // 2. 鍒涘缓鍜屾牸寮忓寲 WSDL 鏂囨。銆�
+            ServiceDescription description = ServiceDescription.Read(stream);
+            //濡傛灉涓嶅瓨鍦ㄥ氨鍒涘缓file鏂囦欢澶�
+            if (Directory.Exists(filePath) == false)
+            {
+                Directory.CreateDirectory(filePath);
+            }
+
+            if (File.Exists(filePath + className + "_" + methodName + ".dll"))
+            {
+                //鍒ゆ柇缂撳瓨鏄惁杩囨湡
+                var cachevalue = HttpRuntime.Cache.Get(className + "_" + methodName);
+                if (cachevalue == null)
+                {
+                    //缂撳瓨杩囨湡鍒犻櫎dll
+                    File.Delete(filePath + className + "_" + methodName + ".dll");
+                }
+                else
+                {
+                    // 濡傛灉缂撳瓨娌℃湁杩囨湡鐩存帴杩斿洖
+                    return;
+                }
+            }
+
+            // 3. 鍒涘缓瀹㈡埛绔唬鐞嗕唬鐞嗙被銆�
+            ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
+            // 鎸囧畾璁块棶鍗忚銆�
+            importer.ProtocolName = "Soap";
+            // 鐢熸垚瀹㈡埛绔唬鐞嗐��
+            importer.Style = ServiceDescriptionImportStyle.Client;
+            importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync;
+            // 娣诲姞 WSDL 鏂囨。銆�
+            importer.AddServiceDescription(description, null, null);
+            // 4. 浣跨敤 CodeDom 缂栬瘧瀹㈡埛绔唬鐞嗙被銆�
+            // 涓轰唬鐞嗙被娣诲姞鍛藉悕绌洪棿锛岀己鐪佷负鍏ㄥ眬绌洪棿銆�
+            CodeNamespace nmspace = new CodeNamespace();
+            CodeCompileUnit unit = new CodeCompileUnit();
+            unit.Namespaces.Add(nmspace);
+            ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit);
+            CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
+            CompilerParameters parameter = new CompilerParameters();
+            parameter.GenerateExecutable = false;
+            // 鍙互鎸囧畾浣犳墍闇�鐨勪换浣曟枃浠跺悕銆�
+            parameter.OutputAssembly = filePath + className + "_" + methodName + ".dll";
+            parameter.ReferencedAssemblies.Add("System.dll");
+            parameter.ReferencedAssemblies.Add("System.XML.dll");
+            parameter.ReferencedAssemblies.Add("System.Web.Services.dll");
+            parameter.ReferencedAssemblies.Add("System.Data.dll");
+            // 鐢熸垚dll鏂囦欢锛屽苟浼氭妸WebService淇℃伅鍐欏叆鍒癲ll閲岄潰
+            CompilerResults result = provider.CompileAssemblyFromDom(parameter, unit);
+            if (result.Errors.HasErrors)
+            {
+                // 鏄剧ず缂栬瘧閿欒淇℃伅
+                System.Text.StringBuilder sb = new StringBuilder();
+                foreach (CompilerError ce in result.Errors)
+                {
+                    sb.Append(ce.ToString());
+                    sb.Append(System.Environment.NewLine);
+                }
+                throw new Exception(sb.ToString());
+            }
+            //璁板綍缂撳瓨
+            var objCache = HttpRuntime.Cache;
+            // 缂撳瓨淇℃伅鍐欏叆dll鏂囦欢
+            objCache.Insert(className + "_" + methodName, "1", null, DateTime.Now.AddMinutes(5), TimeSpan.Zero, CacheItemPriority.High, null);
+        }
+    }
+}
diff --git a/src/Bro.M071.Process/Bro.M071.Process.csproj b/src/Bro.M071.Process/Bro.M071.Process.csproj
index d744dfa..4a340fa 100644
--- a/src/Bro.M071.Process/Bro.M071.Process.csproj
+++ b/src/Bro.M071.Process/Bro.M071.Process.csproj
@@ -121,6 +121,7 @@
     <Compile Include="M071Config.cs" />
     <Compile Include="M071Models.cs" />
     <Compile Include="M071Process.cs" />
+    <Compile Include="M071Process_MES.cs" />
     <Compile Include="M071Process_MotionCard.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="UI\KeyIndicator.cs" />
@@ -211,5 +212,8 @@
       <Name>Bro.UI.Model.Winform</Name>
     </ProjectReference>
   </ItemGroup>
+  <ItemGroup>
+    <WCFMetadata Include="Connected Services\" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
 </Project>
\ No newline at end of file
diff --git a/src/Bro.M071.Process/M071Config.cs b/src/Bro.M071.Process/M071Config.cs
index df1dacb..33cba6e 100644
--- a/src/Bro.M071.Process/M071Config.cs
+++ b/src/Bro.M071.Process/M071Config.cs
@@ -132,9 +132,41 @@
 
         [Category("MES璁剧疆")]
         [Description("true锛氭暟鎹笂浼犺嚦MES false锛氭暟鎹笉涓婁紶")]
+        [DisplayName("MES涓婁紶鍚敤")]
         [ReadOnly(true)]
         public bool IsEnableMESUpload { get; set; } = false;
 
+        [Category("MES璁剧疆")]
+        [Description("true锛氭娴嬬敤鎴风櫥褰� false锛氫笉寮哄埗鐢ㄦ埛鐧诲綍")]
+        [DisplayName("鐢ㄦ埛鐧诲綍妫�娴�")]
+        [Browsable(false)]
+        public bool IsUserLoginCheck { get; set; } = false;
+
+        [Category("MES璁剧疆")]
+        [Description("MES涓婁紶璺緞")]
+        [DisplayName("MES涓婁紶璺緞")]
+        public string MESURL { get; set; } = "";
+
+        [Category("MES璁剧疆")]
+        [Description("绔欑偣缂栫爜")]
+        [DisplayName("绔欑偣缂栫爜")]
+        public string StationCode { get; set; } = "";
+
+        [Category("MES璁剧疆")]
+        [Description("Project缂栫爜")]
+        [DisplayName("Project缂栫爜")]
+        public string ProjectCode { get; set; } = "";
+
+        [Category("MES璁剧疆")]
+        [Description("绾夸綋缂栫爜")]
+        [DisplayName("绾夸綋缂栫爜")]
+        public string LineCode { get; set; } = "";
+
+        [Category("MES璁剧疆")]
+        [Description("楠岃瘉褰撳墠鍏佽鏂板娆℃暟[FALSE=涓嶉獙璇� TRUE=闄愬埗涓ゆ浠ヤ笅(鍖呭惈涓ゆ)]")]
+        [DisplayName("澶氭楠岃瘉寮�鍏�")]
+        public bool IsDisableMultipleCheckTimes { get; set; }
+
         [Category("澶嶄綅璁剧疆")]
         [Description("澶у浣嶉渶瑕佷俊鍙锋寔缁椂闂达紝澶嶄綅淇″彿鎸佺画瓒呭嚭璇ユ椂闂存墽琛屽ぇ澶嶄綅锛屽崟浣嶏細s")]
         [DisplayName("澶у浣嶆寔缁俊鍙烽暱搴�")]
diff --git a/src/Bro.M071.Process/M071Models.cs b/src/Bro.M071.Process/M071Models.cs
index 2e9b2db..44fa305 100644
--- a/src/Bro.M071.Process/M071Models.cs
+++ b/src/Bro.M071.Process/M071Models.cs
@@ -349,6 +349,11 @@
 
             mUnit.Id = this.Id;
             mUnit.Name = this.Name;
+            if (string.IsNullOrWhiteSpace(mUnit.Name))
+            {
+                mUnit.Name = string.Join("-", KeyUnitCollection.Select(u => u.GetDisplayText()));
+            }
+
             mUnit.IsEnabled = this.IsEnabled;
             mUnit.MeasureType = this.MeasureType;
 
diff --git a/src/Bro.M071.Process/M071Process.cs b/src/Bro.M071.Process/M071Process.cs
index a382503..1de633a 100644
--- a/src/Bro.M071.Process/M071Process.cs
+++ b/src/Bro.M071.Process/M071Process.cs
@@ -50,7 +50,6 @@
 
         string _precision = "f3";
 
-
         public override void Open()
         {
             InitialSetting();
@@ -71,6 +70,9 @@
             {
                 _precision = "f" + Config.Precision;
             }
+
+            IncomingCheckMethod = InitialMESWebServiceMethod(IncomingCheckMethodName, out IncomingCheckObj);
+            DataUploadMethod = InitialMESWebServiceMethod(DataUploadMethodName, out DataUploadObj);
         }
 
         private void InitialMotionCardBaseAxisAlarm()
@@ -183,8 +185,6 @@
         }
         #endregion
 
-        public string BarCode { get; set; }
-
         List<ProductionMeasurement> productionList = new List<ProductionMeasurement>();
 
         [ProcessMethod("", "StartJob", "寮�濮嬫壂鎻�", InvokeType.TestInvoke)]
@@ -195,16 +195,25 @@
                 throw new ProcessException(SafetyMsg, null, ExceptionLevel.Fatal);
             }
 
+            string hint = "";
             if (MachineState != MachineState.Ready)
-                throw new ProcessException("鏈哄彴鏈氨缁紝璇峰嬁寮�濮嬫祴閲�", null, ExceptionLevel.Fatal);
+            {
+                hint = "鏈哄彴鏈氨缁紝璇峰嬁寮�濮嬫祴閲�";
+                OnCheckHintUpload?.Invoke(hint, true);
+                throw new ProcessException(hint, null, ExceptionLevel.Fatal);
+            }
 
             if (string.IsNullOrWhiteSpace(BarCode))
             {
+                hint = "鏈緭鍏ヤ骇鍝佹潯鐮侊紝璇峰嬁寮�濮嬫祴閲�";
                 OnClearBarcode?.Invoke();
-                throw new ProcessException("鏈緭鍏ヤ骇鍝佹潯鐮侊紝璇峰嬁寮�濮嬫祴閲�");
+                OnCheckHintUpload?.Invoke(hint, true);
+                throw new ProcessException(hint);
             }
 
             MachineState = MachineState.Running;
+
+            OnCheckHintUpload?.Invoke(hint, true);
             OnMeasureStart?.Invoke();
 
             //var measurements = Config.MeasurementUnitCollection.Where(u => u.IsEnabled).ToList().DeepSerializeClone();
@@ -294,7 +303,7 @@
                   });
 
             LogAsync(DateTime.Now, $"{pMeasure.Barcode}娴嬮噺鍔ㄤ綔瀹屾垚", "");
-            
+
             GC.Collect(0, GCCollectionMode.Optimized);
 
             return new ProcessResponse(true);
@@ -374,7 +383,8 @@
                             {
                                 if (m.KeyUnitCollection.Any(k => k.IsDone == false))
                                 {
-                                    m.Spec.ActualValue = -999;
+                                    //m.Spec.ActualValue = -999;
+                                    m.Spec.ActualValue = null;
                                 }
                                 else
                                 {
@@ -382,7 +392,8 @@
                                     if (!_halconToolDict.ContainsKey(toolKey))
                                     {
                                         LogAsync(DateTime.Now, $"{m.GetDisplayText()}{m.Spec.Code}绠楁硶鏈垵濮嬪寲", "");
-                                        m.Spec.ActualValue = -999;
+                                        //m.Spec.ActualValue = -999;
+                                        m.Spec.ActualValue = null;
                                     }
                                     else
                                     {
@@ -392,7 +403,8 @@
                                         if (array == null || array.Length == 0)
                                         {
                                             LogAsync(DateTime.Now, $"{m.GetDisplayText()}{m.Spec.Code}鏈兘鑾峰彇瀵瑰簲妫�娴嬪��", "");
-                                            m.Spec.ActualValue = -999;
+                                            //m.Spec.ActualValue = -999;
+                                            m.Spec.ActualValue = null;
                                         }
                                         else
                                         {
@@ -401,7 +413,8 @@
                                             if (!_halconToolDict[toolKey].RunProcedure(out string error))
                                             {
                                                 LogAsync(DateTime.Now, $"{m.GetDisplayText()}{m.Spec.Code}绠楁硶寮傚父,{error}", "");
-                                                m.Spec.ActualValue = -999;
+                                                //m.Spec.ActualValue = -999;
+                                                m.Spec.ActualValue = null;
                                             }
                                             else
                                             {
@@ -415,7 +428,8 @@
                                 //LogAsync(DateTime.Now, $"{m.GetDisplayText()}妫�娴嬬粨鏋�", $"{((m.Spec.MeasureResult ?? false) ? "OK" : "NG")}");
 
                                 KeyIndicator indicator = new KeyIndicator(m.Id, m.DisplayLocation);
-                                indicator.Text = (m.Spec.ActualValue == null || m.Spec.ActualValue == -999) ? "NA" : m.Spec.ActualValue.Value.ToString(_precision);
+                                //indicator.Text = (m.Spec.ActualValue == null || m.Spec.ActualValue == -999) ? "NA" : m.Spec.ActualValue.Value.ToString(_precision);
+                                indicator.Text = m.Spec.ActualValue == null ? "NA" : m.Spec.ActualValue.Value.ToString(_precision);
                                 indicator.ResultState = m.Spec.MeasureResult;
                                 pMeasure.ElementList.Add(indicator);
                                 //杈撳嚭鍥惧舰鍩哄厓鍒扮晫闈� 
@@ -435,9 +449,27 @@
                 }
 
                 pMeasure.EndTime = DateTime.Now;
-                bool pResult = pMeasure.Measurements.All(u => u.Spec.MeasureResult == true);
-                pMeasure.PResult = pResult ? "OK" : "NG";
-                OnUpdateResult?.Invoke(DateTime.Now, pResult ? 1 : 0);
+                //bool pResult = pMeasure.Measurements.All(u => u.Spec.MeasureResult == true);
+                //pMeasure.PResult = pResult ? "OK" : "NG";
+                //OnUpdateResult?.Invoke(DateTime.Now, pResult ? 1 : 0);
+                //OnUpdateCT?.Invoke((float)(pMeasure.EndTime.Value - pMeasure.StartTime.Value).TotalSeconds);
+
+                int result = -1;
+                if (pMeasure.Measurements.Any(u => u.Spec.MeasureResult == null))
+                {
+                    pMeasure.PResult = "NA";
+                }
+                else if (pMeasure.Measurements.Any(u => u.Spec.MeasureResult == false))
+                {
+                    pMeasure.PResult = "NG";
+                    result = 0;
+                }
+                else
+                {
+                    pMeasure.PResult = "OK";
+                    result = 1;
+                }
+                OnUpdateResult?.Invoke(DateTime.Now, result);
                 OnUpdateCT?.Invoke((float)(pMeasure.EndTime.Value - pMeasure.StartTime.Value).TotalSeconds);
 
                 LogAsync(DateTime.Now, $"{pMeasure.Barcode} 妫�娴嬪畬鎴愶紝缁撴灉 {pMeasure.PResult}", "");
@@ -447,9 +479,10 @@
 
                 var measurementUnitResultAndKeyUnitDataSet = GetMeasurementUnitResultAndKeyUnitData(pMeasure);
 
-                //MES杈撳嚭 todo
-                if (Config.IsEnableMESUpload)
+                if (pMeasure.PResult != "NA")
                 {
+                    //MES杈撳嚭
+                    MESCheckDataUpload(pMeasure);
                 }
 
                 //Excel鎶ヨ〃杈撳嚭 锛堝崟涓骇鍝佺殑excel瀵煎嚭锛�
@@ -786,7 +819,7 @@
                         if (slantMeasures.Count > 0)
                         {
                             int slantStartCol = slantSheet.Dimension.Columns;
-                            
+
                             var barcodeCell = slantSheet.Cells[1, slantStartCol + 1];
                             barcodeCell.Value = exportData.ProductionMeasurementRecord.ProductionBarcode;
                             SetTitleCell(barcodeCell);
diff --git a/src/Bro.M071.Process/M071Process_MES.cs b/src/Bro.M071.Process/M071Process_MES.cs
new file mode 100644
index 0000000..a5277b3
--- /dev/null
+++ b/src/Bro.M071.Process/M071Process_MES.cs
@@ -0,0 +1,239 @@
+锘縰sing Bro.Common.Helper;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Bro.M071.Process
+{
+    public partial class M071Process
+    {
+        #region MES
+        //WebApiHelper _webApiHelper = new WebApiHelper();
+
+        public Action<string, bool> OnCheckHintUpload { get; set; }
+        public Action<string> OnOperatorLogin { get; set; }
+        #endregion
+
+        private string barcode = "";
+        public string BarCode
+        {
+            get => barcode;
+            set
+            {
+                barcode = value;
+
+                if (!string.IsNullOrWhiteSpace(barcode))
+                {
+                    if (!CheckIncoming(barcode))
+                    {
+                        barcode = "";
+                    }
+                }
+            }
+        }
+
+        private string operatorCode = "";
+        public string OperatorCode
+        {
+            get => operatorCode;
+            set
+            {
+                operatorCode = value;
+
+                if (!string.IsNullOrWhiteSpace(operatorCode))
+                {
+                    OnOperatorLogin?.Invoke(operatorCode);
+
+                    OnCheckHintUpload?.Invoke($"鎿嶄綔鍛樼櫥褰曪細{operatorCode}", false);
+                }
+            }
+        }
+
+        #region WebService Method
+        MethodInfo incomingCheckMethod = null;
+        MethodInfo dataUploadMethod = null;
+
+        const string IncomingCheckMethodName = "CheckFormerData";
+        const string DataUploadMethodName = "HighLowKey_DataUpLoad";
+
+        private object IncomingCheckObj = null;
+        public MethodInfo IncomingCheckMethod
+        {
+            get
+            {
+                if (incomingCheckMethod == null)
+                {
+                    incomingCheckMethod = InitialMESWebServiceMethod(IncomingCheckMethodName, out IncomingCheckObj);
+                }
+
+                return incomingCheckMethod;
+            }
+            set => incomingCheckMethod = value;
+        }
+
+        private object DataUploadObj = null;
+        public MethodInfo DataUploadMethod
+        {
+            get
+            {
+                if (incomingCheckMethod == null)
+                {
+                    incomingCheckMethod = InitialMESWebServiceMethod(DataUploadMethodName, out DataUploadObj);
+                }
+
+                return incomingCheckMethod;
+            }
+            set => incomingCheckMethod = value;
+        }
+
+        private MethodInfo InitialMESWebServiceMethod(string methodName, out object invokeClass)
+        {
+            invokeClass = null;
+
+            if (!Config.IsEnableMESUpload)
+                return null;
+
+            // 璇诲彇閰嶇疆鏂囦欢锛岃幏鍙栭厤缃俊鎭�
+            var urlParas = Config.MESURL.Split(new char[] { '/', '.' }, StringSplitOptions.RemoveEmptyEntries);
+            string className = urlParas[urlParas.Length - 2];
+            string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "MESAPI");
+            if (Directory.Exists(filePath))
+            {
+                Directory.CreateDirectory(filePath);
+            }
+
+            // 璋冪敤WebServiceHelper
+            WebServiceHelper.CreateWebServiceDLL(Config.MESURL, className, methodName, filePath);
+
+            // 璇诲彇dll鍐呭
+            byte[] filedata = File.ReadAllBytes(filePath + className + "_" + methodName + ".dll");
+            // 鍔犺浇绋嬪簭闆嗕俊鎭�
+            Assembly asm = Assembly.Load(filedata);
+            Type t = asm.GetType(className);
+
+            // 鍒涘缓瀹炰緥
+            invokeClass = Activator.CreateInstance(t);
+            return t.GetMethod(methodName);
+        }
+        #endregion
+
+        private bool CheckIncoming(string barcode)
+        {
+            if (!Config.IsEnableMESUpload)
+                return true;
+
+            //dynamic paras = new
+            //{
+            //    FGcode = barcode,
+            //    station = Config.StationCode,
+            //};
+
+            //string url = $"{Config.MESURL}CheckFormerData";
+            //string paraStr = JsonConvert.SerializeObject(paras);
+            //LogAsync(DateTime.Now, $"MES鍏ユ枡妫�娴� {url}", paraStr);
+
+            IncomingCheckMethod = InitialMESWebServiceMethod(IncomingCheckMethodName, out IncomingCheckObj);
+
+            Stopwatch sw = new Stopwatch();
+            sw.Start();
+            //var result = _webApiHelper.dooPost(url, paraStr);
+
+            object[] paras = new object[] { barcode, Config.StationCode };
+            var result = IncomingCheckMethod?.Invoke(IncomingCheckObj, paras).ToString();
+            var mesReturn = (MESIncomingCheckReturn)int.Parse(result);
+            sw.Stop();
+            LogAsync(DateTime.Now, $"{barcode}浜у搧鏉$爜妫�娴嬶紝{result}|{mesReturn.ToString()}", $"鑰楁椂锛歿sw.ElapsedMilliseconds}ms");
+
+            bool isOK = mesReturn == MESIncomingCheckReturn.妫�娴婸ASS;
+            OnCheckHintUpload?.Invoke("鏉$爜妫�娴�" + mesReturn.ToString(), !isOK);
+
+            return isOK;
+        }
+
+        private void MESCheckDataUpload(ProductionMeasurement pMeasure)
+        {
+            if (!Config.IsEnableMESUpload)
+                return;
+
+            //dynamic paras = new
+            //{
+            //    checkTimes = Config.IsDisableMultipleCheckTimes,
+            //    Project = Config.ProjectCode,
+            //    FGcode = pMeasure.Barcode,
+            //    CheckTime = pMeasure.EndTime.Value.ToString("yyyy-MM-dd HH:mm:ss"),
+            //    ProcessCode = Config.StationCode,
+            //    Result = pMeasure.PResult == "OK" ? "PASS" : "FAIL",
+            //    Line = Config.LineCode,
+            //    SlantCheckData = GetMESSlantData(pMeasure),
+            //    AlignmentCheckData = GetMESAlignmentData(pMeasure),
+            //};
+
+            //string url = $"{Config.MESURL}HighLowKey_DataUpload";
+            //string paraStr = JsonConvert.SerializeObject(paras);
+            //LogAsync(DateTime.Now, $"MES鏁版嵁涓婁紶 {url}", paraStr);
+
+            DataUploadMethod = InitialMESWebServiceMethod(DataUploadMethodName, out DataUploadObj);
+
+            Stopwatch sw = new Stopwatch();
+            sw.Start();
+            //var result = _webApiHelper.dooPost(url, paraStr);
+
+            DateTime checkTime = pMeasure.EndTime.Value;
+            object[] paras = new object[]
+            {
+                Config.IsDisableMultipleCheckTimes,
+                Config.ProjectCode,
+                pMeasure.Barcode,
+                checkTime.ToString("yyyy-MM-dd HH:mm:ss"),
+                Config.StationCode,
+                pMeasure.PResult == "OK" ? "PASS" : "FAIL",
+                Config.LineCode,
+                GetMESSlantData(pMeasure),
+                GetMESAlignmentData(pMeasure)
+            };
+
+            //LogAsync(DateTime.Now, $"{barcode}浜у搧妫�娴嬫暟鎹笂浼�", JsonConvert.SerializeObject(paras));
+
+            var result = DataUploadMethod?.Invoke(DataUploadObj, paras).ToString();
+            var mesReturn = (MESUploadReturn)int.Parse(result);
+            sw.Stop();
+            LogAsync(DateTime.Now, $"{barcode}浜у搧妫�娴嬫暟鎹笂浼狅紝{result}|{mesReturn.ToString()}", $"鑰楁椂锛歿sw.ElapsedMilliseconds}ms");
+
+            OnCheckHintUpload?.Invoke("妫�娴嬫暟鎹�" + mesReturn.ToString(), mesReturn != MESUploadReturn.涓婁紶鎴愬姛);
+        }
+
+        private string GetMESAlignmentData(ProductionMeasurement pMeasure)
+        {
+            return string.Join(",", pMeasure.Measurements.Where(u => u.MeasureType == "Alignment").Select(u => $"{u.Name}:{u.Spec.ActualValue.Value.ToString(_precision)}"));
+        }
+
+        private string GetMESSlantData(ProductionMeasurement pMeasure)
+        {
+            return string.Join(",", pMeasure.Measurements.Where(u => u.MeasureType == "Slant").Select(u => $"{u.Name}:{u.Spec.ActualValue.Value.ToString(_precision)}"));
+        }
+    }
+
+    public enum MESIncomingCheckReturn
+    {
+        涓婁紶缁撴灉鏈煡 = -3,
+        鏈煡璇㈠埌宸ュ簭淇℃伅 = -2,
+        鏈煡璇㈠埌SN淇℃伅 = -1,
+        妫�娴婩AIL = 0,
+        妫�娴婸ASS = 1,
+    }
+
+    public enum MESUploadReturn
+    {
+        涓婁紶缁撴灉鏈煡 = -1,
+        涓婁紶澶辫触 = 0,
+        涓婁紶鎴愬姛 = 1,
+        宸ュ簭妫�娴嬪紓甯� = 2,
+        妫�娴嬫鏁板紓甯� = 3,
+    }
+}
diff --git a/src/Bro.M071.Process/Properties/AssemblyInfo.cs b/src/Bro.M071.Process/Properties/AssemblyInfo.cs
index 8d31d69..e18e474 100644
--- a/src/Bro.M071.Process/Properties/AssemblyInfo.cs
+++ b/src/Bro.M071.Process/Properties/AssemblyInfo.cs
@@ -32,5 +32,5 @@
 //鍙互鎸囧畾鎵�鏈夎繖浜涘�硷紝涔熷彲浠ヤ娇鐢ㄢ�滅敓鎴愬彿鈥濆拰鈥滀慨璁㈠彿鈥濈殑榛樿鍊�
 //閫氳繃浣跨敤 "*"锛屽涓嬫墍绀�:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: AssemblyVersion("1.0.2.0")]
+[assembly: AssemblyFileVersion("1.0.2.0")]
diff --git a/src/Bro.M071.Process/UI/M071_MainForm.Designer.cs b/src/Bro.M071.Process/UI/M071_MainForm.Designer.cs
index a702101..a98bd9b 100644
--- a/src/Bro.M071.Process/UI/M071_MainForm.Designer.cs
+++ b/src/Bro.M071.Process/UI/M071_MainForm.Designer.cs
@@ -50,6 +50,9 @@
             this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
             this.propGridKeyIndicator = new System.Windows.Forms.PropertyGrid();
             this.timer1 = new System.Windows.Forms.Timer(this.components);
+            this.lblOperator = new System.Windows.Forms.Label();
+            this.stStripHint = new System.Windows.Forms.StatusStrip();
+            this.tsslError = new System.Windows.Forms.ToolStripStatusLabel();
             this.contextMenuStrip1.SuspendLayout();
             this.plImage.SuspendLayout();
             this.tscEditLocation.ContentPanel.SuspendLayout();
@@ -59,6 +62,7 @@
             this.splitContainer1.Panel1.SuspendLayout();
             this.splitContainer1.Panel2.SuspendLayout();
             this.splitContainer1.SuspendLayout();
+            this.stStripHint.SuspendLayout();
             this.SuspendLayout();
             // 
             // contextMenuStrip1
@@ -109,7 +113,7 @@
             this.btnReset.Cursor = System.Windows.Forms.Cursors.Hand;
             this.btnReset.Font = new System.Drawing.Font("瀹嬩綋", 11F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.World, ((byte)(134)));
             this.btnReset.ForeColor = System.Drawing.Color.DarkGreen;
-            this.btnReset.Location = new System.Drawing.Point(531, 8);
+            this.btnReset.Location = new System.Drawing.Point(800, 8);
             this.btnReset.Name = "btnReset";
             this.btnReset.Size = new System.Drawing.Size(141, 35);
             this.btnReset.TabIndex = 5;
@@ -125,7 +129,7 @@
             this.btnStartMeasure.Cursor = System.Windows.Forms.Cursors.Hand;
             this.btnStartMeasure.Font = new System.Drawing.Font("瀹嬩綋", 14F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.World, ((byte)(134)));
             this.btnStartMeasure.ForeColor = System.Drawing.Color.DarkGreen;
-            this.btnStartMeasure.Location = new System.Drawing.Point(678, 8);
+            this.btnStartMeasure.Location = new System.Drawing.Point(947, 8);
             this.btnStartMeasure.Name = "btnStartMeasure";
             this.btnStartMeasure.Size = new System.Drawing.Size(110, 35);
             this.btnStartMeasure.TabIndex = 5;
@@ -137,7 +141,7 @@
             // 
             this.lblCT.AutoSize = true;
             this.lblCT.Font = new System.Drawing.Font("Tahoma", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World, ((byte)(134)));
-            this.lblCT.Location = new System.Drawing.Point(464, 19);
+            this.lblCT.Location = new System.Drawing.Point(550, 21);
             this.lblCT.Name = "lblCT";
             this.lblCT.Size = new System.Drawing.Size(35, 14);
             this.lblCT.TabIndex = 4;
@@ -146,7 +150,7 @@
             // txtBarcode
             // 
             this.txtBarcode.Font = new System.Drawing.Font("Tahoma", 14F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World, ((byte)(134)));
-            this.txtBarcode.Location = new System.Drawing.Point(138, 13);
+            this.txtBarcode.Location = new System.Drawing.Point(222, 13);
             this.txtBarcode.Name = "txtBarcode";
             this.txtBarcode.Size = new System.Drawing.Size(261, 24);
             this.txtBarcode.TabIndex = 3;
@@ -159,7 +163,7 @@
             this.lblProductionState.BackColor = System.Drawing.Color.Lime;
             this.lblProductionState.Font = new System.Drawing.Font("Tahoma", 20F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.World, ((byte)(134)));
             this.lblProductionState.ForeColor = System.Drawing.Color.DarkGreen;
-            this.lblProductionState.Location = new System.Drawing.Point(405, 13);
+            this.lblProductionState.Location = new System.Drawing.Point(489, 13);
             this.lblProductionState.Name = "lblProductionState";
             this.lblProductionState.Size = new System.Drawing.Size(39, 24);
             this.lblProductionState.TabIndex = 2;
@@ -171,7 +175,7 @@
             this.lblMachineState.BackColor = System.Drawing.Color.Lime;
             this.lblMachineState.Font = new System.Drawing.Font("Tahoma", 20F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.World, ((byte)(134)));
             this.lblMachineState.ForeColor = System.Drawing.Color.DarkGreen;
-            this.lblMachineState.Location = new System.Drawing.Point(22, 12);
+            this.lblMachineState.Location = new System.Drawing.Point(137, 13);
             this.lblMachineState.Name = "lblMachineState";
             this.lblMachineState.Size = new System.Drawing.Size(79, 24);
             this.lblMachineState.TabIndex = 2;
@@ -186,7 +190,7 @@
             this.plImage.Controls.Add(this.tscEditLocation);
             this.plImage.Location = new System.Drawing.Point(1, 47);
             this.plImage.Name = "plImage";
-            this.plImage.Size = new System.Drawing.Size(796, 304);
+            this.plImage.Size = new System.Drawing.Size(1065, 279);
             this.plImage.TabIndex = 1;
             // 
             // tscEditLocation
@@ -195,11 +199,11 @@
             // tscEditLocation.ContentPanel
             // 
             this.tscEditLocation.ContentPanel.Controls.Add(this.tableLayoutPanel1);
-            this.tscEditLocation.ContentPanel.Size = new System.Drawing.Size(209, 279);
+            this.tscEditLocation.ContentPanel.Size = new System.Drawing.Size(209, 254);
             this.tscEditLocation.Dock = System.Windows.Forms.DockStyle.Right;
-            this.tscEditLocation.Location = new System.Drawing.Point(587, 0);
+            this.tscEditLocation.Location = new System.Drawing.Point(856, 0);
             this.tscEditLocation.Name = "tscEditLocation";
-            this.tscEditLocation.Size = new System.Drawing.Size(209, 304);
+            this.tscEditLocation.Size = new System.Drawing.Size(209, 279);
             this.tscEditLocation.TabIndex = 0;
             this.tscEditLocation.Text = "toolStripContainer1";
             this.tscEditLocation.Visible = false;
@@ -218,7 +222,7 @@
             this.tableLayoutPanel1.RowCount = 2;
             this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
             this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
-            this.tableLayoutPanel1.Size = new System.Drawing.Size(209, 279);
+            this.tableLayoutPanel1.Size = new System.Drawing.Size(209, 254);
             this.tableLayoutPanel1.TabIndex = 0;
             // 
             // btnConfirmEdit
@@ -227,7 +231,7 @@
             | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
             this.btnConfirmEdit.Font = new System.Drawing.Font("瀹嬩綋", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            this.btnConfirmEdit.Location = new System.Drawing.Point(3, 246);
+            this.btnConfirmEdit.Location = new System.Drawing.Point(3, 221);
             this.btnConfirmEdit.Name = "btnConfirmEdit";
             this.btnConfirmEdit.Size = new System.Drawing.Size(98, 30);
             this.btnConfirmEdit.TabIndex = 0;
@@ -241,7 +245,7 @@
             | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
             this.btnCancelEdit.Font = new System.Drawing.Font("瀹嬩綋", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
-            this.btnCancelEdit.Location = new System.Drawing.Point(107, 246);
+            this.btnCancelEdit.Location = new System.Drawing.Point(107, 221);
             this.btnCancelEdit.Name = "btnCancelEdit";
             this.btnCancelEdit.Size = new System.Drawing.Size(99, 30);
             this.btnCancelEdit.TabIndex = 0;
@@ -264,8 +268,8 @@
             // splitContainer1.Panel2
             // 
             this.splitContainer1.Panel2.Controls.Add(this.propGridKeyIndicator);
-            this.splitContainer1.Size = new System.Drawing.Size(203, 237);
-            this.splitContainer1.SplitterDistance = 136;
+            this.splitContainer1.Size = new System.Drawing.Size(203, 212);
+            this.splitContainer1.SplitterDistance = 121;
             this.splitContainer1.TabIndex = 1;
             // 
             // lvMeasures
@@ -280,7 +284,7 @@
             this.lvMeasures.Location = new System.Drawing.Point(0, 0);
             this.lvMeasures.MultiSelect = false;
             this.lvMeasures.Name = "lvMeasures";
-            this.lvMeasures.Size = new System.Drawing.Size(203, 136);
+            this.lvMeasures.Size = new System.Drawing.Size(203, 121);
             this.lvMeasures.TabIndex = 0;
             this.lvMeasures.UseCompatibleStateImageBehavior = false;
             this.lvMeasures.View = System.Windows.Forms.View.List;
@@ -297,7 +301,7 @@
             this.propGridKeyIndicator.Dock = System.Windows.Forms.DockStyle.Fill;
             this.propGridKeyIndicator.Location = new System.Drawing.Point(0, 0);
             this.propGridKeyIndicator.Name = "propGridKeyIndicator";
-            this.propGridKeyIndicator.Size = new System.Drawing.Size(203, 97);
+            this.propGridKeyIndicator.Size = new System.Drawing.Size(203, 87);
             this.propGridKeyIndicator.TabIndex = 0;
             this.propGridKeyIndicator.ToolbarVisible = false;
             // 
@@ -306,11 +310,45 @@
             this.timer1.Interval = 3000;
             this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
             // 
+            // lblOperator
+            // 
+            this.lblOperator.AutoSize = true;
+            this.lblOperator.Cursor = System.Windows.Forms.Cursors.Hand;
+            this.lblOperator.Font = new System.Drawing.Font("Tahoma", 14F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.World, ((byte)(134)));
+            this.lblOperator.Location = new System.Drawing.Point(22, 17);
+            this.lblOperator.Name = "lblOperator";
+            this.lblOperator.Size = new System.Drawing.Size(78, 17);
+            this.lblOperator.TabIndex = 6;
+            this.lblOperator.Text = "OPERATOR";
+            this.lblOperator.DoubleClick += new System.EventHandler(this.lblOperator_DoubleClick);
+            // 
+            // stStripHint
+            // 
+            this.stStripHint.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.tsslError});
+            this.stStripHint.Location = new System.Drawing.Point(0, 329);
+            this.stStripHint.Name = "stStripHint";
+            this.stStripHint.Size = new System.Drawing.Size(1069, 22);
+            this.stStripHint.TabIndex = 7;
+            this.stStripHint.Text = "statusStrip1";
+            this.stStripHint.Visible = false;
+            // 
+            // tsslError
+            // 
+            this.tsslError.BackColor = System.Drawing.Color.Red;
+            this.tsslError.ForeColor = System.Drawing.SystemColors.Control;
+            this.tsslError.Margin = new System.Windows.Forms.Padding(10, 3, 0, 2);
+            this.tsslError.Name = "tsslError";
+            this.tsslError.Size = new System.Drawing.Size(131, 17);
+            this.tsslError.Text = "toolStripStatusLabel1";
+            // 
             // M071_MainForm
             // 
             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
-            this.ClientSize = new System.Drawing.Size(800, 351);
+            this.ClientSize = new System.Drawing.Size(1069, 351);
+            this.Controls.Add(this.stStripHint);
+            this.Controls.Add(this.lblOperator);
             this.Controls.Add(this.btnReset);
             this.Controls.Add(this.btnStartMeasure);
             this.Controls.Add(this.lblCT);
@@ -332,6 +370,8 @@
             this.splitContainer1.Panel2.ResumeLayout(false);
             ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
             this.splitContainer1.ResumeLayout(false);
+            this.stStripHint.ResumeLayout(false);
+            this.stStripHint.PerformLayout();
             this.ResumeLayout(false);
             this.PerformLayout();
 
@@ -360,5 +400,8 @@
         private System.Windows.Forms.ColumnHeader columnHeader1;
         private System.Windows.Forms.ToolStripMenuItem tsmiRefreshLabels;
         private System.Windows.Forms.Timer timer1;
+        private System.Windows.Forms.Label lblOperator;
+        private System.Windows.Forms.StatusStrip stStripHint;
+        private System.Windows.Forms.ToolStripStatusLabel tsslError;
     }
 }
\ No newline at end of file
diff --git a/src/Bro.M071.Process/UI/M071_MainForm.cs b/src/Bro.M071.Process/UI/M071_MainForm.cs
index 7035785..4893258 100644
--- a/src/Bro.M071.Process/UI/M071_MainForm.cs
+++ b/src/Bro.M071.Process/UI/M071_MainForm.cs
@@ -1,6 +1,7 @@
 锘縰sing Bro.Common.Base;
 using Bro.Common.Helper;
 using Bro.UI.Model.Winform;
+using Bro.UI.Model.Winform.UI;
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -44,6 +45,8 @@
                    timer1.Enabled = true;
 
                    btnReset.Text = $"澶嶄綅锛堥暱鎸墈Config.FullResetRequiredDuration}绉掑ぇ澶嶄綅锛�";
+
+                   lblCT.Text = tsslError.Text = "";
                };
         }
 
@@ -90,6 +93,8 @@
                            item.Tag = u.Id;
                            lvMeasures.Items.Add(item);
                        });
+
+                       lblOperator.Text = string.IsNullOrWhiteSpace(Process_M071.OperatorCode) ? "NotLogin" : Process_M071.OperatorCode;
                    }));
             }
             catch (Exception ex)
@@ -117,6 +122,9 @@
 
             Process_M071.OnElementUpdated -= Process_M071_OnElementUpdated;
             Process_M071.OnElementUpdated += Process_M071_OnElementUpdated;
+
+            Process_M071.OnCheckHintUpload = OnCheckHintUpload;
+            Process_M071.OnOperatorLogin = OnOperatorLogin;
         }
 
         private void Config_PropertyChanged(object sender, PropertyChangedEventArgs e)
@@ -312,7 +320,7 @@
 
             if (e.KeyValue == 13)
             {
-                txtBarcode.Text = _barcode;
+                Process_M071.BarCode = txtBarcode.Text = _barcode;
                 _barcode = "";
             }
 
@@ -324,7 +332,7 @@
 
         private void txtBarcode_TextChanged(object sender, EventArgs e)
         {
-            Process_M071.BarCode = txtBarcode.Text.Trim();
+            //Process_M071.BarCode = txtBarcode.Text.Trim();
         }
 
         private void M071_MainForm_OnClearBarcode()
@@ -409,11 +417,17 @@
                     lblProductionState.ForeColor = Color.White;
                     lblProductionState.Text = "OK";
                 }
-                else
+                else if (result == 0)
                 {
                     lblProductionState.BackColor = Color.Red;
                     lblProductionState.ForeColor = Color.White;
                     lblProductionState.Text = "NG";
+                }
+                else
+                {
+                    lblProductionState.BackColor = Color.White;
+                    lblProductionState.ForeColor = Color.Red;
+                    lblProductionState.Text = "NA";
                 }
 
                 //btnStartMeasure.Text = "寮�濮嬫祴閲�";
@@ -504,5 +518,44 @@
         {
             cvImage.Refresh();
         }
+
+        private void lblOperator_DoubleClick(object sender, EventArgs e)
+        {
+            InputWindow inputFrm = new InputWindow("璇疯緭鍏ユ搷浣滃憳宸ュ彿");
+            if (inputFrm.ShowDialog() == DialogResult.OK)
+            {
+                Process_M071.OperatorCode = inputFrm.Input;
+            }
+        }
+
+        private void OnOperatorLogin(string operatorCode)
+        {
+            this.Invoke(new Action(() =>
+            {
+                lblOperator.Text = operatorCode;
+            }));
+        }
+
+        private async void OnCheckHintUpload(string hintMsg, bool isAlarm)
+        {
+            await Task.Run(() =>
+            {
+                this.Invoke(new Action(() =>
+                {
+                    if (!string.IsNullOrWhiteSpace(hintMsg))
+                    {
+                        stStripHint.Visible = true;
+                        tsslError.Text = hintMsg;
+
+                        tsslError.BackColor = isAlarm ? Color.Red : Color.Green;
+                    }
+                    else
+                    {
+                        stStripHint.Visible = false;
+                        tsslError.Text = "";
+                    }
+                }));
+            });
+        }
     }
 }
diff --git a/src/Bro.M071.Process/UI/M071_MainForm.resx b/src/Bro.M071.Process/UI/M071_MainForm.resx
index 2b01b4a..a122d15 100644
--- a/src/Bro.M071.Process/UI/M071_MainForm.resx
+++ b/src/Bro.M071.Process/UI/M071_MainForm.resx
@@ -123,4 +123,7 @@
   <metadata name="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
     <value>182, 17</value>
   </metadata>
+  <metadata name="stStripHint.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>272, 17</value>
+  </metadata>
 </root>
\ No newline at end of file
diff --git a/src/Bro.UI.Model.Winform/Bro.UI.Model.Winform.csproj b/src/Bro.UI.Model.Winform/Bro.UI.Model.Winform.csproj
index 400bb5d..d757cd8 100644
--- a/src/Bro.UI.Model.Winform/Bro.UI.Model.Winform.csproj
+++ b/src/Bro.UI.Model.Winform/Bro.UI.Model.Winform.csproj
@@ -140,6 +140,12 @@
     <Compile Include="UI\DockContent\MenuFrmBase.Designer.cs">
       <DependentUpon>MenuFrmBase.cs</DependentUpon>
     </Compile>
+    <Compile Include="UI\InputWindow.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="UI\InputWindow.Designer.cs">
+      <DependentUpon>InputWindow.cs</DependentUpon>
+    </Compile>
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\Bro.Common.Model\Bro.Common.Model.csproj">
@@ -173,6 +179,9 @@
     <EmbeddedResource Include="UI\DockContent\MenuFrmBase.resx">
       <DependentUpon>MenuFrmBase.cs</DependentUpon>
     </EmbeddedResource>
+    <EmbeddedResource Include="UI\InputWindow.resx">
+      <DependentUpon>InputWindow.cs</DependentUpon>
+    </EmbeddedResource>
   </ItemGroup>
   <ItemGroup>
     <None Include="UI\ROIImg\grid.png" />
diff --git a/src/Bro.UI.Model.Winform/UI/InputWindow.Designer.cs b/src/Bro.UI.Model.Winform/UI/InputWindow.Designer.cs
new file mode 100644
index 0000000..adfd600
--- /dev/null
+++ b/src/Bro.UI.Model.Winform/UI/InputWindow.Designer.cs
@@ -0,0 +1,108 @@
+锘�
+namespace Bro.UI.Model.Winform.UI
+{
+    partial class InputWindow
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.lblTitle = new System.Windows.Forms.Label();
+            this.txtInput = new System.Windows.Forms.TextBox();
+            this.btnConfirm = new System.Windows.Forms.Button();
+            this.btnCancel = new System.Windows.Forms.Button();
+            this.SuspendLayout();
+            // 
+            // lblTitle
+            // 
+            this.lblTitle.AutoSize = true;
+            this.lblTitle.Location = new System.Drawing.Point(30, 17);
+            this.lblTitle.Name = "lblTitle";
+            this.lblTitle.Size = new System.Drawing.Size(42, 17);
+            this.lblTitle.TabIndex = 0;
+            this.lblTitle.Text = "label1";
+            // 
+            // txtInput
+            // 
+            this.txtInput.Location = new System.Drawing.Point(33, 49);
+            this.txtInput.Name = "txtInput";
+            this.txtInput.Size = new System.Drawing.Size(301, 24);
+            this.txtInput.TabIndex = 1;
+            this.txtInput.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.txtInput_KeyPress);
+            // 
+            // btnConfirm
+            // 
+            this.btnConfirm.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(128)))), ((int)(((byte)(255)))), ((int)(((byte)(128)))));
+            this.btnConfirm.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+            this.btnConfirm.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.btnConfirm.Location = new System.Drawing.Point(259, 84);
+            this.btnConfirm.Name = "btnConfirm";
+            this.btnConfirm.Size = new System.Drawing.Size(75, 30);
+            this.btnConfirm.TabIndex = 2;
+            this.btnConfirm.Text = "纭";
+            this.btnConfirm.UseVisualStyleBackColor = false;
+            this.btnConfirm.Click += new System.EventHandler(this.btnConfirm_Click);
+            // 
+            // btnCancel
+            // 
+            this.btnCancel.BackColor = System.Drawing.SystemColors.Control;
+            this.btnCancel.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+            this.btnCancel.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.btnCancel.Location = new System.Drawing.Point(178, 84);
+            this.btnCancel.Name = "btnCancel";
+            this.btnCancel.Size = new System.Drawing.Size(75, 30);
+            this.btnCancel.TabIndex = 2;
+            this.btnCancel.Text = "鍙栨秷";
+            this.btnCancel.UseVisualStyleBackColor = false;
+            this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
+            // 
+            // InputWindow
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 16F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(370, 123);
+            this.ControlBox = false;
+            this.Controls.Add(this.btnCancel);
+            this.Controls.Add(this.btnConfirm);
+            this.Controls.Add(this.txtInput);
+            this.Controls.Add(this.lblTitle);
+            this.Font = new System.Drawing.Font("Tahoma", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
+            this.Name = "InputWindow";
+            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+            this.Text = "InputWindow";
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Label lblTitle;
+        private System.Windows.Forms.TextBox txtInput;
+        private System.Windows.Forms.Button btnConfirm;
+        private System.Windows.Forms.Button btnCancel;
+    }
+}
\ No newline at end of file
diff --git a/src/Bro.UI.Model.Winform/UI/InputWindow.cs b/src/Bro.UI.Model.Winform/UI/InputWindow.cs
new file mode 100644
index 0000000..29a5e2e
--- /dev/null
+++ b/src/Bro.UI.Model.Winform/UI/InputWindow.cs
@@ -0,0 +1,65 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace Bro.UI.Model.Winform.UI
+{
+    public partial class InputWindow : Form
+    {
+        public InputWindow()
+        {
+            InitializeComponent();
+        }
+
+        public string Title
+        {
+            set => lblTitle.Text = value;
+        }
+
+        public string Input { get; set; }
+
+        public InputWindow(string title)
+        {
+            InitializeComponent();
+
+            Title = title;
+        }
+
+        private void btnCancel_Click(object sender, EventArgs e)
+        {
+            this.DialogResult = DialogResult.Cancel;
+        }
+
+        private void btnConfirm_Click(object sender, EventArgs e)
+        {
+            ConfirmInput();
+        }
+
+        private void ConfirmInput()
+        {
+            Input = txtInput.Text.Trim();
+
+            if (string.IsNullOrWhiteSpace(Input))
+            {
+                MessageBox.Show("杈撳叆涓嶈兘涓虹┖");
+                return;
+            }
+
+            this.DialogResult = DialogResult.OK;
+        }
+
+        private void txtInput_KeyPress(object sender, KeyPressEventArgs e)
+        {
+            if (e.KeyChar == 13)
+            {
+                ConfirmInput();
+            }
+        }
+    }
+}
diff --git a/src/Bro.UI.Model.Winform/UI/InputWindow.resx b/src/Bro.UI.Model.Winform/UI/InputWindow.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/src/Bro.UI.Model.Winform/UI/InputWindow.resx
@@ -0,0 +1,120 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file

--
Gitblit v1.8.0