领胜LDS 键盘AOI检测项目
xcd
2020-07-09 5b6ffebeeee53e375cf8f8d5c30c51f03ad1d96e
Merge branch 'master' of http://gitblit.broconcentric.com:8088/r/M071
17个文件已修改
558 ■■■■ 已修改文件
src/Bro.Device.GTSCard/GTSCardDriver.cs 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.DBManager/ExcelExportHelper.cs 178 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.DBManager/MeasurementUnitResultManager.cs 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Model/Model/MeasurementUnitResult.cs 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/Bro.M071.Process.csproj 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/M071Config.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/M071Models.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.M071.Process/M071Process.cs 161 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Device.Winform/MotionCard/CtrlMotionCardAxisOperation.Designer.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Device.Winform/MotionCard/CtrlMotionCardAxisOperation.cs 51 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Device.Winform/MotionCard/CtrlMotionCardAxisStatus.Designer.cs 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Device.Winform/MotionCard/CtrlMotionCardAxisStatus.resx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Device.Winform/MotionCard/CtrlMotionCardIOStatus.Designer.cs 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Device.Winform/MotionCard/CtrlMotionCardIOStatus.resx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Device.Winform/MotionCard/CtrlMotionCardRunBase.cs 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Device.Winform/MotionCard/FrmMotionCardOperationBase.Designer.cs 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.UI.Device.Winform/MotionCard/FrmMotionCardOperationBase.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Bro.Device.GTSCard/GTSCardDriver.cs
@@ -387,7 +387,7 @@
        public override async Task<bool> SingleAxisMoving(MovingOption optionPara)
        {
            return await Task.Run(() =>
            {
            {
                axisImmediatePauseHandleDict[optionPara.AxisIndex].WaitOne();
                bool isSuccessAndStop = false;
                try
@@ -459,7 +459,8 @@
            {
                throw new Exception("轴" + axisNum + "获取规划位置异常,错误码:" + ret);
            }
            position = prfpos / IConfig.AxisVelocityRatio;
            var AxisRatio = IConfig.AxisSettings.FirstOrDefault(u => u.AxisIndex == axisNum) == null ? 1 : IConfig.AxisSettings.FirstOrDefault(u => u.AxisIndex == axisNum).AxisRatio;
            position = prfpos / AxisRatio;
            return position;
        }
@@ -479,7 +480,8 @@
                {
                    throw new Exception("轴" + axisNum + "获取目标位置异常,错误码:" + ret);
                }
                position = pPos / IConfig.AxisVelocityRatio;
                var AxisRatio = IConfig.AxisSettings.FirstOrDefault(u => u.AxisIndex == axisNum) == null ? 1 : IConfig.AxisSettings.FirstOrDefault(u => u.AxisIndex == axisNum).AxisRatio;
                position = pPos / AxisRatio;
                return position;
            }
        }
@@ -488,7 +490,7 @@
        /// 获取规划速度
        /// </summary>
        /// <param name="axisNum">Axis number</param>
        /// <returns></returns>
        /// <returns>速度脉冲</returns>
        public double GetPrfVelocity(int axisNum)
        {
            double prfVel = 0;
@@ -498,7 +500,6 @@
            {
                throw new Exception("轴" + axisNum + "获取规划速度异常,错误码:" + ret);
            }
            prfVel = prfVel / IConfig.AxisVelocityRatio;
            return prfVel;
        }
@@ -506,7 +507,7 @@
        /// 获取当前速度
        /// </summary>
        /// <param name="axisNum">Axis number</param>
        /// <returns></returns>
        /// <returns>速度脉冲</returns>
        public double GetVelocity(int axisNum)
        {
            double vel = 0;
@@ -515,7 +516,6 @@
            {
                throw new Exception("轴" + axisNum + "获取当前速度异常,错误码:" + ret);
            }
            vel = vel / IConfig.AxisVelocityRatio;
            return vel;
        }
@@ -600,11 +600,12 @@
                int currentPosition = (int)GetPosition(optionPara.AxisIndex);
                int dPosition = optionPara.Destination + currentPosition;
                int timeout = optionPara.MovingTimeout;
                var AxisRatio = IConfig.AxisSettings.FirstOrDefault(u => u.AxisIndex == optionPara.AxisIndex) == null ? 1 : IConfig.AxisSettings.FirstOrDefault(u => u.AxisIndex == optionPara.AxisIndex).AxisRatio;
                while (CurrentState == DeviceState.DSOpen)
                {
                    //设置 运动参数
                    isSuccessSetAxisParam = SetAxisParam(optionPara);
                    ret = GTSCardAPI.GT_SetPrfPos((short)IConfig.CardNum, (short)optionPara.AxisIndex, (int)(dPosition * IConfig.AxisVelocityRatio));// 设置规划位置
                    ret = GTSCardAPI.GT_SetPrfPos((short)IConfig.CardNum, (short)optionPara.AxisIndex, (int)(dPosition * AxisRatio));// 设置规划位置
                    ret = GTSCardAPI.GT_Update((short)IConfig.CardNum, 1 << (optionPara.AxisIndex - 1));//更新运动
                    if (ret != (short)GTSRetCode.GRCRunOK)
@@ -675,11 +676,12 @@
                short ret = 0;
                bool isSuccessSetAxisParam = false;
                int timeout = optionPara.MovingTimeout;
                while (CurrentState == DeviceState.DSOpen&&!_isPause)
                var AxisRatio = IConfig.AxisSettings.FirstOrDefault(u => u.AxisIndex == optionPara.AxisIndex) == null ? 1 : IConfig.AxisSettings.FirstOrDefault(u => u.AxisIndex == optionPara.AxisIndex).AxisRatio;
                while (CurrentState == DeviceState.DSOpen && !_isPause)
                {
                    //设置 运动参数
                    isSuccessSetAxisParam = SetAxisParam(optionPara);
                    ret = GTSCardAPI.GT_SetPrfPos((short)IConfig.CardNum, (short)optionPara.AxisIndex, (int)(optionPara.Destination * IConfig.AxisVelocityRatio));// 设置规划位置
                    ret = GTSCardAPI.GT_SetPrfPos((short)IConfig.CardNum, (short)optionPara.AxisIndex, (int)(optionPara.Destination * AxisRatio));// 设置规划位置
                    ret = GTSCardAPI.GT_Update((short)IConfig.CardNum, 1 << (optionPara.AxisIndex - 1));//更新运动
                    if (ret != (short)GTSRetCode.GRCRunOK)
src/Bro.M071.DBManager/ExcelExportHelper.cs
@@ -8,6 +8,19 @@
namespace Bro.M071.DBManager
{
    public class ExcelExportSet
    {
        public List<string> Worksheets { get; set; }
        /// <summary>
        /// Key: Worksheet的名称 Value:Worksheet对应的列名集合(key 为要导出的列名 value 为导出后显示的列名)
        /// </summary>
        public Dictionary<string, Dictionary<string, string>> WorksheetColumns { get; set; }
        public Dictionary<string, DataTable> WorksheetDataTable { get; set; }
    }
    /// <summary>
    /// Excel导出帮助类
    /// </summary>
@@ -20,21 +33,27 @@
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <returns></returns>
        public static DataTable ListToDataTable<T>(List<T> data)
        public static DataTable ListToDataTable<T>(List<T> data, Dictionary<string, string> worksheetColumns)
        {
            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
            DataTable dataTable = new DataTable();
            for (int i = 0; i < properties.Count; i++)
            Dictionary<string, string> tempColumns = new Dictionary<string, string>();
            foreach (var column in worksheetColumns)
            {
                PropertyDescriptor property = properties[i];
                dataTable.Columns.Add(property.Name, Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType);
                PropertyDescriptor property = properties.Find(column.Key, true);
                if (property != null)
                {
                    dataTable.Columns.Add(column.Value, Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType);
                    tempColumns[column.Key] = column.Value;
                }
            }
            object[] values = new object[properties.Count];
            object[] values = new object[tempColumns.Count];
            foreach (T item in data)
            {
                for (int i = 0; i < values.Length; i++)
                for (int i = 0; i < tempColumns.Count; i++)
                {
                    values[i] = properties[i].GetValue(item);
                    PropertyDescriptor property = properties.Find(tempColumns.ElementAt(i).Key, true);
                    values[i] = property.GetValue(item);
                }
                dataTable.Rows.Add(values);
            }
@@ -45,99 +64,94 @@
        /// 导出Excel
        /// </summary>
        /// <param name="dataTable">数据源</param>
        /// <param name="heading">工作簿Worksheet</param>
        /// <param name="worksheet">工作簿Worksheet</param>
        /// <param name="showSrNo">//是否显示行编号</param>
        /// <param name="columnsToTake">要导出的列</param>
        /// <returns></returns>
        public static byte[] ExportExcel(DataTable dataTable, string heading = "", bool showSrNo = false, params string[] columnsToTake)
        public static byte[] ExportExcel(ExcelExportSet excelExportDto, bool showSrNo = false)
        {
            byte[] result;
            byte[] result = null;
            using (ExcelPackage package = new ExcelPackage())
            {
                ExcelWorksheet workSheet = package.Workbook.Worksheets.Add($"{heading}Data");
                int startRowFrom = string.IsNullOrEmpty(heading) ? 1 : 3;  //开始的行
                //是否显示行编号
                if (showSrNo)
                foreach (var worksheet in excelExportDto.Worksheets)
                {
                    DataColumn dataColumn = dataTable.Columns.Add("#", typeof(int));
                    dataColumn.SetOrdinal(0);
                    int index = 1;
                    foreach (DataRow item in dataTable.Rows)
                    var dataTable = excelExportDto.WorksheetDataTable[worksheet];
                    ExcelWorksheet workSheet = package.Workbook.Worksheets.Add($"{worksheet}");
                    int startRowFrom = string.IsNullOrEmpty(worksheet) ? 1 : 3;  //开始的行
                                                                                 //是否显示行编号
                    if (showSrNo)
                    {
                        item[0] = index;
                        index++;
                        DataColumn dataColumn = dataTable.Columns.Add("#", typeof(int));
                        dataColumn.SetOrdinal(0);
                        int index = 1;
                        foreach (DataRow item in dataTable.Rows)
                        {
                            item[0] = index;
                            index++;
                        }
                    }
                }
                //Add Content Into the Excel File
                workSheet.Cells["A" + startRowFrom].LoadFromDataTable(dataTable, true);
                // autofit width of cells with small content
                int columnIndex = 1;
                foreach (DataColumn item in dataTable.Columns)
                {
                    ExcelRange columnCells = workSheet.Cells[workSheet.Dimension.Start.Row, columnIndex, workSheet.Dimension.End.Row, columnIndex];
                    int maxLength = columnCells.Max(cell => cell.Value.ToString().Count());
                    if (maxLength < 150)
                    //Add Content Into the Excel File
                    workSheet.Cells["A" + startRowFrom].LoadFromDataTable(dataTable, true);
                    // autofit width of cells with small content
                    int columnIndex = 1;
                    foreach (DataColumn item in dataTable.Columns)
                    {
                        workSheet.Column(columnIndex).AutoFit();
                        ExcelRange columnCells = workSheet.Cells[workSheet.Dimension.Start.Row, columnIndex, workSheet.Dimension.End.Row, columnIndex];
                        int maxLength = columnCells.Max(cell => cell.Value.ToString().Count());
                        if (maxLength < 150)
                        {
                            workSheet.Column(columnIndex).AutoFit();
                        }
                        columnIndex++;
                    }
                    columnIndex++;
                }
                // format header - bold, yellow on black
                using (ExcelRange r = workSheet.Cells[startRowFrom, 1, startRowFrom, dataTable.Columns.Count])
                {
                    r.Style.Font.Color.SetColor(System.Drawing.Color.White);
                    r.Style.Font.Bold = true;
                    r.Style.Fill.PatternType = ExcelFillStyle.Solid;
                    r.Style.Fill.BackgroundColor.SetColor(System.Drawing.ColorTranslator.FromHtml("#1fb5ad"));
                }
                // format cells - add borders
                using (ExcelRange r = workSheet.Cells[startRowFrom + 1, 1, startRowFrom + dataTable.Rows.Count, dataTable.Columns.Count])
                {
                    r.Style.Border.Top.Style = ExcelBorderStyle.Thin;
                    r.Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
                    r.Style.Border.Left.Style = ExcelBorderStyle.Thin;
                    r.Style.Border.Right.Style = ExcelBorderStyle.Thin;
                    r.Style.Border.Top.Color.SetColor(System.Drawing.Color.Black);
                    r.Style.Border.Bottom.Color.SetColor(System.Drawing.Color.Black);
                    r.Style.Border.Left.Color.SetColor(System.Drawing.Color.Black);
                    r.Style.Border.Right.Color.SetColor(System.Drawing.Color.Black);
                }
                // removed ignored columns
                for (int i = dataTable.Columns.Count - 1; i >= 0; i--)
                {
                    if (i == 0 && showSrNo)
                    // format header - bold, yellow on black
                    using (ExcelRange r = workSheet.Cells[startRowFrom, 1, startRowFrom, dataTable.Columns.Count])
                    {
                        continue;
                        r.Style.Font.Color.SetColor(System.Drawing.Color.White);
                        r.Style.Font.Bold = true;
                        r.Style.Fill.PatternType = ExcelFillStyle.Solid;
                        r.Style.Fill.BackgroundColor.SetColor(System.Drawing.ColorTranslator.FromHtml("#1fb5ad"));
                    }
                    if (!columnsToTake.Contains(dataTable.Columns[i].ColumnName))
                    // format cells - add borders
                    using (ExcelRange r = workSheet.Cells[startRowFrom + 1, 1, startRowFrom + dataTable.Rows.Count, dataTable.Columns.Count])
                    {
                        workSheet.DeleteColumn(i + 1);
                        r.Style.Border.Top.Style = ExcelBorderStyle.Thin;
                        r.Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
                        r.Style.Border.Left.Style = ExcelBorderStyle.Thin;
                        r.Style.Border.Right.Style = ExcelBorderStyle.Thin;
                        r.Style.Border.Top.Color.SetColor(System.Drawing.Color.Black);
                        r.Style.Border.Bottom.Color.SetColor(System.Drawing.Color.Black);
                        r.Style.Border.Left.Color.SetColor(System.Drawing.Color.Black);
                        r.Style.Border.Right.Color.SetColor(System.Drawing.Color.Black);
                    }
                    if (!string.IsNullOrEmpty(worksheet))
                    {
                        workSheet.Cells["A1"].Value = worksheet;
                        workSheet.Cells["A1"].Style.Font.Size = 20;
                        workSheet.InsertColumn(1, 1);
                        workSheet.InsertRow(1, 1);
                        workSheet.Column(1).Width = 5;
                    }
                    result = package.GetAsByteArray();
                }
                if (!string.IsNullOrEmpty(heading))
                {
                    workSheet.Cells["A1"].Value = heading;
                    workSheet.Cells["A1"].Style.Font.Size = 20;
                    workSheet.InsertColumn(1, 1);
                    workSheet.InsertRow(1, 1);
                    workSheet.Column(1).Width = 5;
                }
                result = package.GetAsByteArray();
            }
            return result;
        }
        /// <summary>
        /// 导出Excel
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <param name="heading"></param>
        /// <param name="isShowSlNo"></param>
        /// <param name="columnsToTake"></param>
        /// <returns></returns>
        public static byte[] ExportExcel<T>(List<T> data, string heading = "", bool isShowSlNo = false, params string[] columnsToTake)
        {
            return ExportExcel(ListToDataTable(data), heading, isShowSlNo, columnsToTake);
        }
        ///// <summary>
        ///// 导出Excel
        ///// </summary>
        ///// <typeparam name="T"></typeparam>
        ///// <param name="data"></param>
        ///// <param name="heading"></param>
        ///// <param name="isShowSlNo"></param>
        ///// <param name="columnsToTake"></param>
        ///// <returns></returns>
        //public static byte[] ExportExcel<T>(List<T> data, string heading = "", bool isShowSlNo = false, params string[] columnsToTake)
        //{
        //    ExcelExportSet excelExport = new ExcelExportSet();
        //    excelExport.
        //    return ExportExcel(ListToDataTable(data), heading, isShowSlNo, columnsToTake);
        //}
    }
}
src/Bro.M071.DBManager/MeasurementUnitResultManager.cs
@@ -72,11 +72,11 @@
                            //into pmList
                            select new MeasurementUnitResult_DTO
                            {
                                ProductionMeasurementRecord= productionMeasurementRecords,
                                MeasurementUnitResult= measurementUnitResult
                                ProductionCode = productionMeasurementRecords.ProductionCode,
                                ProductionBarcode = productionMeasurementRecords.ProductionBarcode
                            };
                var pageList = query.OrderBy(u => u.ProductionMeasurementRecord.OperationStartTime).ToPagedList(request);
                var pageList = query.OrderBy(u => u.CREATE_TIME).ToPagedList(request);
                request.TotalNum = mList.Count();
                return pageList;
            }
src/Bro.M071.Model/Model/MeasurementUnitResult.cs
@@ -1,5 +1,6 @@

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Bro.M071.Model.Model
@@ -68,17 +69,48 @@
        public string MeasurementResult { get; set; }
    }
    public class MeasurementUnitResult_DTO
    public class MeasurementUnitResult_DTO : MeasurementUnitResult
    {
        //产品相关
        /// <summary>
        /// 产品记录
        /// 产品编码
        /// </summary>
        public string ProductionCode { get; set; }
        /// <summary>
        /// 产品条码
        /// </summary>
        public string ProductionBarcode { get; set; }
    }
    public class ProductionMeasurementUnitResultAndKeyUnitDataSet
    {
        public ProductionMeasurementRecords ProductionMeasurementRecord { get; set; }
        /// <summary>
        /// 关系数据
        /// </summary>
        public List<MeasurementAndKeyDataRelation> MeasurementAndKeyDataRelationList{ get; set; }
        /// <summary>
        /// 检测结果
        /// </summary>
        public MeasurementUnitResult MeasurementUnitResult { get; set; }
        public List<MeasurementUnitResult> MeasurementUnitResultList { get; set; }
        /// <summary>
        /// 原始数据
        /// </summary>
        public List<KeyUnitData> KeyUnitDataList { get; set; }
        public ProductionMeasurementUnitResultAndKeyUnitDataSet()
        {
            ProductionMeasurementRecord = new ProductionMeasurementRecords();
            MeasurementUnitResultList = new List<MeasurementUnitResult>();
            KeyUnitDataList = new List<KeyUnitData>();
        }
    }
src/Bro.M071.Process/Bro.M071.Process.csproj
@@ -179,6 +179,10 @@
      <Project>{1A3CBFE7-3F78-42C3-95C5-10360450DBEA}</Project>
      <Name>Bro.Common.Model</Name>
    </ProjectReference>
    <ProjectReference Include="..\Bro.M071.DBManager\Bro.M071.DBManager.csproj">
      <Project>{230B0FFF-F6AF-45FE-AAF7-B4B66250DD58}</Project>
      <Name>Bro.M071.DBManager</Name>
    </ProjectReference>
    <ProjectReference Include="..\Bro.M071.Model\Bro.M071.Model.csproj">
      <Project>{AD645C48-5811-4B1E-B81F-D35D5E6B577F}</Project>
      <Name>Bro.M071.Model</Name>
src/Bro.M071.Process/M071Config.cs
@@ -67,6 +67,12 @@
        [Editor(typeof(ComplexCollectionEditor<MeasurementUnit>), typeof(UITypeEditor))]
        public List<MeasurementUnit> MeasurementUnitCollection { get; set; } = new List<MeasurementUnit>();
        [Category("检测设置")]
        [DisplayName("结果数据保存路径")]
        [Description("检测结果数据保存路径")]
        [Editor(typeof(FoldDialogEditor), typeof(UITypeEditor))]
        public string ResultDataSaveFolder { get; set; } = "";
        [Category("图片保存配置")]
        [Description("单键图片保存配置")]
        [TypeConverter(typeof(ComplexObjectConvert))]
src/Bro.M071.Process/M071Models.cs
@@ -219,6 +219,7 @@
    public class ProductionMeasurement : INotifyPropertyChanged, IDisposable
    {
        public string Barcode;
        public string PResult;
        public List<MeasurementUnit> Measurements = new List<MeasurementUnit>();
src/Bro.M071.Process/M071Process.cs
@@ -2,7 +2,9 @@
using Bro.Common.Helper;
using Bro.Common.Interface;
using Bro.Common.Model;
using Bro.M071.DBManager;
using Bro.M071.Model;
using Bro.M071.Model.Model;
using Bro.Process;
using HalconDotNet;
using Newtonsoft.Json;
@@ -59,8 +61,8 @@
        private void InitialSetting()
        {
            ////数据库迁移检查
            //DatabaseInitialize.Initialize();
            //数据库迁移检查
            DatabaseInitialize.Initialize();
            MotionCardSettingCheck();
@@ -364,19 +366,23 @@
                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);
                OnUpdateCT?.Invoke((float)(pMeasure.EndTime.Value - pMeasure.StartTime.Value).TotalSeconds);
                LogAsync(DateTime.Now, $"{pMeasure.Barcode} 检测完成,结果 {(pResult ? "OK" : "NG")}", "");
                LogAsync(DateTime.Now, $"{pMeasure.Barcode} 检测完成,结果 {pMeasure.PResult}", "");
                if (MachineState == MachineState.Running)
                    MachineState = MachineState.Ready;
                var measurementUnitResultAndKeyUnitDataSet = GetMeasurementUnitResultAndKeyUnitData(pMeasure);
                //MES输出 todo
                //Excel报表输出 todo
                //数据库保存 todo
                //Excel报表输出 (单个产品的excel导出)
                ExportProductionExcel(measurementUnitResultAndKeyUnitDataSet);
                //数据库保存
                SaveProductionData(measurementUnitResultAndKeyUnitDataSet);
                SaveWholeImage(pMeasure);
@@ -385,6 +391,149 @@
            }
        }
        KeyUnitDataManager keyUnitDataManager = new KeyUnitDataManager();
        MeasurementUnitResultManager measurementUnitResultManager = new MeasurementUnitResultManager();
        MeasurementAndKeyDataRelationManager measurementAndKeyDataRelationManager = new MeasurementAndKeyDataRelationManager();
        ProductionMeasurementRecordsManager productionMeasurementRecordsManager = new ProductionMeasurementRecordsManager();
        static object dataSaveLock = new object();
        private async void SaveProductionData(ProductionMeasurementUnitResultAndKeyUnitDataSet measurementUnitResultAndKeyUnitDataSet)
        {
            await Task.Run(() =>
            {
                try
                {
                    lock (dataSaveLock)
                    {
                        // 获取 产品数据 并保存
                        var productionMeasurementRecords = measurementUnitResultAndKeyUnitDataSet.ProductionMeasurementRecord;
                        productionMeasurementRecordsManager.CreateModel(productionMeasurementRecords);
                        // 获取 原始数据 并保存
                        var keyUnitDatas = measurementUnitResultAndKeyUnitDataSet.KeyUnitDataList;
                        keyUnitDataManager.BatchAddKeyUnitData(keyUnitDatas);
                        // 获取 检测结果数据 并保存
                        var measurementUnitResults = measurementUnitResultAndKeyUnitDataSet.MeasurementUnitResultList;
                        measurementUnitResultManager.BatchAddMeasurementUnitResult(measurementUnitResults);
                        // 获取 关系数据并保存
                        var measurementAndKeyDataRelationList = measurementUnitResultAndKeyUnitDataSet.MeasurementAndKeyDataRelationList;
                        measurementAndKeyDataRelationManager.BatchAddMeasurementAndKeyDataRelation(measurementAndKeyDataRelationList);
                    }
                }
                catch (Exception ex)
                {
                    LogAsync(DateTime.Now, "数据保存异常", ex.GetExceptionMessage());
                }
            });
        }
        private ProductionMeasurementUnitResultAndKeyUnitDataSet GetMeasurementUnitResultAndKeyUnitData(ProductionMeasurement pData)
        {
            ProductionMeasurementUnitResultAndKeyUnitDataSet measurementUnitResultAndKeyUnitDataSet = new ProductionMeasurementUnitResultAndKeyUnitDataSet();
            try
            {
                //产品数据
                ProductionMeasurementRecords productionMeasurementRecords = new ProductionMeasurementRecords();
                //关系数据
                List<MeasurementAndKeyDataRelation> measurementAndKeyDataRelationList = new List<MeasurementAndKeyDataRelation>();
                //原始数据
                List<KeyUnitData> keyUnitDatas = new List<KeyUnitData>();
                // 单个产品的测量汇总
                List<MeasurementUnitResult> measurementUnitResults = new List<MeasurementUnitResult>();
                productionMeasurementRecords.ProductionBarcode = pData.Barcode;
                productionMeasurementRecords.ProductionCode = ProductionCode;
                productionMeasurementRecords.ProductionResult = pData.PResult;
                productionMeasurementRecords.OperationStartTime = pData.StartTime.GetValueOrDefault();
                productionMeasurementRecords.OperationEndTime = pData.EndTime.GetValueOrDefault();
                measurementUnitResultAndKeyUnitDataSet.ProductionMeasurementRecord = productionMeasurementRecords;
                foreach (var MeasurementUnitResult in pData.Measurements)//获取到单个测量项结果
                {
                    MeasurementUnitResult measurementUnitResult = new MeasurementUnitResult();
                    measurementUnitResult.ProductionMeasurementRecordsId = productionMeasurementRecords.ID;
                    measurementUnitResult.MeasurementName = MeasurementUnitResult.Name;
                    measurementUnitResult.MeasurementType = MeasurementUnitResult.MeasureType;
                    measurementUnitResult.MeasurementValue = "";
                    measurementUnitResult.MeasurementResult = MeasurementUnitResult.Spec.MeasureResult.Value ? "OK" : "NG";
                    measurementUnitResults.Add(measurementUnitResult);
                    foreach (var keyUnit in MeasurementUnitResult.KeyUnitCollection)//获取单个键的测量结果
                    {
                        foreach (var keyValue in keyUnit.MeasureValueDict)//获取单个键的单个测量item 结果
                        {
                            KeyUnitData keyUnitData = new KeyUnitData();
                            keyUnitData.Key = keyUnit.Key;
                            keyUnitData.MeasurementItem = keyValue.Key;
                            keyUnitData.ItemValue = keyValue.Value.ToString();
                            keyUnitDatas.Add(keyUnitData);
                            MeasurementAndKeyDataRelation measurementAndKeyDataRelation = new MeasurementAndKeyDataRelation();
                            measurementAndKeyDataRelation.MeasurementUnitResultId = measurementUnitResult.ID;
                            measurementAndKeyDataRelation.KeyUnitDataId = keyUnitData.ID;
                            measurementAndKeyDataRelationList.Add(measurementAndKeyDataRelation);
                        }
                    }
                }
                measurementUnitResultAndKeyUnitDataSet.ProductionMeasurementRecord = productionMeasurementRecords;
                measurementUnitResultAndKeyUnitDataSet.MeasurementAndKeyDataRelationList = measurementAndKeyDataRelationList;
                measurementUnitResultAndKeyUnitDataSet.KeyUnitDataList = keyUnitDatas;
                measurementUnitResultAndKeyUnitDataSet.MeasurementUnitResultList = measurementUnitResults;
            }
            catch (Exception ex)
            {
                LogAsync(DateTime.Now, "数据获取异常", ex.GetExceptionMessage());
            }
            return measurementUnitResultAndKeyUnitDataSet;
        }
        private async void ExportProductionExcel(ProductionMeasurementUnitResultAndKeyUnitDataSet measurementUnitResultAndKeyUnitDataSet)
        {
            await Task.Run(() =>
            {
                ExcelExportSet excelExportDto = new ExcelExportSet();
                excelExportDto.Worksheets = new List<string>() { "原始数据", "检测结果" };
                var keyUnitColumns = new Dictionary<string, string>()
                {
                    {"Key", "键"},
                    {"MeasurementItem", "检测项"},
                    {"ItemValue", "检测值"}
                };
                var measurementUnitResultColumns = new Dictionary<string, string>()
                {
                    {"MeasurementName", "检测名称"},
                    {"MeasurementType", "检测类型"},
                    {"MeasurementValue", "检测值"},
                    {"MeasurementResult", "检测结果"},
                };
                excelExportDto.WorksheetColumns[excelExportDto.Worksheets[0]] = keyUnitColumns;
                excelExportDto.WorksheetColumns[excelExportDto.Worksheets[1]] = measurementUnitResultColumns;
                excelExportDto.WorksheetDataTable[excelExportDto.Worksheets[0]] = ExcelExportHelper.ListToDataTable(measurementUnitResultAndKeyUnitDataSet.KeyUnitDataList, keyUnitColumns);
                excelExportDto.WorksheetDataTable[excelExportDto.Worksheets[1]] = ExcelExportHelper.ListToDataTable(measurementUnitResultAndKeyUnitDataSet.MeasurementUnitResultList, measurementUnitResultColumns); ;
                byte[] filecontent = ExcelExportHelper.ExportExcel(excelExportDto, false);
                string dir = Path.Combine(Config.ImageSaveFolder, DateTime.Now.ToString("yyyyMMdd"));
                if (!Directory.Exists(dir))
                {
                    Directory.CreateDirectory(dir);
                }
                FileStream fs = new FileStream(Path.Combine(dir, $"{measurementUnitResultAndKeyUnitDataSet.ProductionMeasurementRecord.ProductionBarcode}_{DateTime.Now.ToString("HHmmss")}.xlsx"), FileMode.Create, FileAccess.Write);
                fs.Write(filecontent, 0, filecontent.Length);
                fs.Flush();
                fs.Close();
            });
        }
        #region 图像保存
        private void SaveWholeImage(ProductionMeasurement pMeasure)
        {
src/Bro.UI.Device.Winform/MotionCard/CtrlMotionCardAxisOperation.Designer.cs
@@ -228,6 +228,8 @@
            this.buttonNegative.Text = "负向";
            this.buttonNegative.UseVisualStyleBackColor = true;
            this.buttonNegative.Click += new System.EventHandler(this.buttonNegative_Click);
            this.buttonNegative.MouseDown += new System.Windows.Forms.MouseEventHandler(this.buttonNegative_MouseDown);
            this.buttonNegative.MouseUp += new System.Windows.Forms.MouseEventHandler(this.buttonNegative_MouseUp);
            // 
            // textBoxJogDec
            // 
@@ -245,6 +247,8 @@
            this.buttonPositive.Text = "正向";
            this.buttonPositive.UseVisualStyleBackColor = true;
            this.buttonPositive.Click += new System.EventHandler(this.buttonPositive_Click);
            this.buttonPositive.MouseDown += new System.Windows.Forms.MouseEventHandler(this.buttonPositive_MouseDown);
            this.buttonPositive.MouseUp += new System.Windows.Forms.MouseEventHandler(this.buttonPositive_MouseUp);
            // 
            // textBoxJogAcc
            // 
src/Bro.UI.Device.Winform/MotionCard/CtrlMotionCardAxisOperation.cs
@@ -37,21 +37,8 @@
            groupBoxAxisOperration.Text = $"运动轴:{axisIndex}-{axisName}";
        }
        private void buttonPositive_Click(object sender, EventArgs e)
        {
            var opConfig = new MotionOperationCollection();
            MovingOption movingOption = new MovingOption();
            movingOption.AxisIndex = _axisIndex;
            movingOption.MoveMode = MotionMode.Jog;
            movingOption.VelocityPara.Acc = Convert.ToDouble(textBoxJogAcc.Text);
            movingOption.VelocityPara.Dec = Convert.ToDouble(textBoxJogDec.Text);
            movingOption.VelocityPara.Velocity= Convert.ToDouble(textBoxJogVel.Text);
            opConfig.MovingOps.Add(movingOption);
            MotionCard.MoveToPoint(opConfig);
        }
        private void buttonNegative_Click(object sender, EventArgs e)
        private void buttonPositive_MouseDown(object sender, MouseEventArgs e)
        {
            var opConfig = new MotionOperationCollection();
            MovingOption movingOption = new MovingOption();
@@ -63,6 +50,40 @@
            opConfig.MovingOps.Add(movingOption);
            MotionCard.MoveToPoint(opConfig);
        }
        private void buttonPositive_MouseUp(object sender, MouseEventArgs e)
        {
            MotionCard.MoveStop(_axisIndex, 0);
        }
        private void buttonNegative_MouseUp(object sender, MouseEventArgs e)
        {
            MotionCard.MoveStop(_axisIndex, 0);
        }
        private void buttonNegative_MouseDown(object sender, MouseEventArgs e)
        {
            var opConfig = new MotionOperationCollection();
            MovingOption movingOption = new MovingOption();
            movingOption.AxisIndex = _axisIndex;
            movingOption.MoveMode = MotionMode.Jog;
            movingOption.VelocityPara.Acc = Convert.ToDouble(textBoxJogAcc.Text);
            movingOption.VelocityPara.Dec = Convert.ToDouble(textBoxJogDec.Text);
            movingOption.VelocityPara.Velocity = -Convert.ToDouble(textBoxJogVel.Text);
            opConfig.MovingOps.Add(movingOption);
            MotionCard.MoveToPoint(opConfig);
        }
        private void buttonPositive_Click(object sender, EventArgs e)
        {
        }
        private void buttonNegative_Click(object sender, EventArgs e)
        {
        }
        private void buttonStart_Click(object sender, EventArgs e)
@@ -82,7 +103,7 @@
        private void buttonStop_Click(object sender, EventArgs e)
        {
            MotionCard.StateChange(DeviceState.DSPause);
            MotionCard.MoveStop(_axisIndex, 0);
        }
    }
}
src/Bro.UI.Device.Winform/MotionCard/CtrlMotionCardAxisStatus.Designer.cs
@@ -44,7 +44,7 @@
            this.label4 = new System.Windows.Forms.Label();
            this.label3 = new System.Windows.Forms.Label();
            this.label2 = new System.Windows.Forms.Label();
            this.timer1 = new System.Windows.Forms.Timer(this.components);
            this.timerAxisStatus = new System.Windows.Forms.Timer(this.components);
            this.groupBoxAxisStatus.SuspendLayout();
            this.SuspendLayout();
            // 
@@ -194,9 +194,11 @@
            this.label2.TabIndex = 2;
            this.label2.Text = "规划位置:";
            // 
            // timer1
            // timerAxisStatus
            // 
            this.timer1.Tick += new System.EventHandler(this.RefreshStatus);
            this.timerAxisStatus.Enabled = true;
            this.timerAxisStatus.Interval = 200;
            this.timerAxisStatus.Tick += new System.EventHandler(this.RefreshStatus);
            // 
            // CtrlMotionCardAxisStatus
            // 
@@ -228,6 +230,6 @@
        private System.Windows.Forms.Label label4;
        private System.Windows.Forms.Label label3;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.Timer timer1;
        private System.Windows.Forms.Timer timerAxisStatus;
    }
}
src/Bro.UI.Device.Winform/MotionCard/CtrlMotionCardAxisStatus.resx
@@ -117,7 +117,7 @@
  <resheader name="writer">
    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <metadata name="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
  <metadata name="timerAxisStatus.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
    <value>17, 17</value>
  </metadata>
</root>
src/Bro.UI.Device.Winform/MotionCard/CtrlMotionCardIOStatus.Designer.cs
@@ -64,7 +64,7 @@
            this.ioIn6 = new Bro.UI.Model.Winform.IOIndicatorCtrl();
            this.ioIn5 = new Bro.UI.Model.Winform.IOIndicatorCtrl();
            this.ioIn1 = new Bro.UI.Model.Winform.IOIndicatorCtrl();
            this.timer1 = new System.Windows.Forms.Timer(this.components);
            this.timerIOStatus = new System.Windows.Forms.Timer(this.components);
            this.tableLayoutPanel1.SuspendLayout();
            this.groupBoxIOOut.SuspendLayout();
            this.groupBoxIOIn.SuspendLayout();
@@ -425,11 +425,11 @@
            this.ioIn1.Size = new System.Drawing.Size(90, 24);
            this.ioIn1.TabIndex = 4;
            // 
            // timer1
            // timerIOStatus
            // 
            this.timer1.Enabled = true;
            this.timer1.Interval = 200;
            this.timer1.Tick += new System.EventHandler(this.RefreshIOStatus);
            this.timerIOStatus.Enabled = true;
            this.timerIOStatus.Interval = 200;
            this.timerIOStatus.Tick += new System.EventHandler(this.RefreshIOStatus);
            // 
            // CtrlMotionCardIOStatus
            // 
@@ -482,6 +482,6 @@
        private Model.Winform.IOIndicatorCtrl ioOut6;
        private Model.Winform.IOIndicatorCtrl ioOut5;
        private Model.Winform.IOIndicatorCtrl ioOut1;
        private System.Windows.Forms.Timer timer1;
        private System.Windows.Forms.Timer timerIOStatus;
    }
}
src/Bro.UI.Device.Winform/MotionCard/CtrlMotionCardIOStatus.resx
@@ -117,7 +117,7 @@
  <resheader name="writer">
    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <metadata name="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
  <metadata name="timerIOStatus.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
    <value>17, 17</value>
  </metadata>
</root>
src/Bro.UI.Device.Winform/MotionCard/CtrlMotionCardRunBase.cs
@@ -9,6 +9,7 @@
using System.Windows.Forms;
using Bro.Common.Interface;
using Bro.Common.Base;
using Bro.Common.Model;
namespace Bro.UI.Device.Winform
{
@@ -27,6 +28,13 @@
            InitialLayout();
        }
        public IDevice Device { get; set; }
        protected MotionCardBase MotionCard
        {
            get => Device as MotionCardBase;
        }
        private void MotionCard_OnMonitorInvoke(DateTime arg1, string arg2, IDevice arg3, IMonitorSet arg4)
        {
            throw new NotImplementedException();
@@ -36,25 +44,23 @@
        {
            foreach (var axisConfig in MotionCard.IConfig.AxisSettings.FindAll(u => u.IsAxisEnabled))
            {
                var axisMovingStatus = MotionCard.AxisMovingOptionValues.FirstOrDefault(u=>u.AxisIndex== axisConfig.AxisIndex);
                if (axisMovingStatus!=null)
                var axisMovingStatus = MotionCard.AxisMovingOptionValues.FirstOrDefault(u => u.AxisIndex == axisConfig.AxisIndex);
                if (axisMovingStatus == null)
                {
                    CtrlMotionCardAxisStatus ctrlMotionCardAxisStatus = new CtrlMotionCardAxisStatus(axisMovingStatus);
                    ctrlMotionCardAxisStatus.Dock = DockStyle.Fill;
                    flowLayoutPanel1.Controls.Add(ctrlMotionCardAxisStatus);
                    axisMovingStatus = new AxisMovingStatus();
                }
                CtrlMotionCardAxisStatus ctrlMotionCardAxisStatus = new CtrlMotionCardAxisStatus(axisMovingStatus);
                //ctrlMotionCardAxisStatus.Dock = DockStyle.Fill;
                flowLayoutPanel1.Controls.Add(ctrlMotionCardAxisStatus);
            }
            CtrlMotionCardIOStatus ctrlMotionCardIOStatus = new CtrlMotionCardIOStatus();
            CtrlMotionCardIOStatus ctrlMotionCardIOStatus = new CtrlMotionCardIOStatus(MotionCard.MonitorValues);
            //ctrlMotionCardIOStatus.Dock = DockStyle.Fill;
            flowLayoutPanel2.Controls.Add(ctrlMotionCardIOStatus);
        }
        public IDevice Device { get; set; }
        protected MotionCardBase MotionCard
        {
            get => Device as MotionCardBase;
        }
        private void buttonMotionCardOperation_Click(object sender, EventArgs e)
        {
src/Bro.UI.Device.Winform/MotionCard/FrmMotionCardOperationBase.Designer.cs
@@ -63,7 +63,7 @@
            this.tableLayoutPanel1.Name = "tableLayoutPanel1";
            this.tableLayoutPanel1.RowCount = 1;
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
            this.tableLayoutPanel1.Size = new System.Drawing.Size(484, 681);
            this.tableLayoutPanel1.Size = new System.Drawing.Size(574, 681);
            this.tableLayoutPanel1.TabIndex = 0;
            // 
            // tabControl1
@@ -74,7 +74,7 @@
            this.tabControl1.Location = new System.Drawing.Point(3, 3);
            this.tabControl1.Name = "tabControl1";
            this.tabControl1.SelectedIndex = 0;
            this.tabControl1.Size = new System.Drawing.Size(478, 675);
            this.tabControl1.Size = new System.Drawing.Size(568, 675);
            this.tabControl1.TabIndex = 12;
            // 
            // tabPage1
@@ -83,7 +83,7 @@
            this.tabPage1.Location = new System.Drawing.Point(4, 22);
            this.tabPage1.Name = "tabPage1";
            this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
            this.tabPage1.Size = new System.Drawing.Size(470, 649);
            this.tabPage1.Size = new System.Drawing.Size(560, 649);
            this.tabPage1.TabIndex = 0;
            this.tabPage1.Text = "快捷操作";
            this.tabPage1.UseVisualStyleBackColor = true;
@@ -93,7 +93,7 @@
            this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.flowLayoutPanel1.Location = new System.Drawing.Point(3, 3);
            this.flowLayoutPanel1.Name = "flowLayoutPanel1";
            this.flowLayoutPanel1.Size = new System.Drawing.Size(464, 643);
            this.flowLayoutPanel1.Size = new System.Drawing.Size(554, 643);
            this.flowLayoutPanel1.TabIndex = 0;
            // 
            // tabPage2
@@ -102,7 +102,7 @@
            this.tabPage2.Location = new System.Drawing.Point(4, 22);
            this.tabPage2.Name = "tabPage2";
            this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
            this.tabPage2.Size = new System.Drawing.Size(470, 649);
            this.tabPage2.Size = new System.Drawing.Size(560, 649);
            this.tabPage2.TabIndex = 1;
            this.tabPage2.Text = "通用操作";
            this.tabPage2.UseVisualStyleBackColor = true;
@@ -119,7 +119,7 @@
            this.tableLayoutPanel3.RowCount = 2;
            this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 120F));
            this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
            this.tableLayoutPanel3.Size = new System.Drawing.Size(464, 643);
            this.tableLayoutPanel3.Size = new System.Drawing.Size(554, 643);
            this.tableLayoutPanel3.TabIndex = 0;
            // 
            // groupBoxPara
@@ -128,7 +128,7 @@
            this.groupBoxPara.Dock = System.Windows.Forms.DockStyle.Fill;
            this.groupBoxPara.Location = new System.Drawing.Point(3, 123);
            this.groupBoxPara.Name = "groupBoxPara";
            this.groupBoxPara.Size = new System.Drawing.Size(458, 517);
            this.groupBoxPara.Size = new System.Drawing.Size(548, 517);
            this.groupBoxPara.TabIndex = 13;
            this.groupBoxPara.TabStop = false;
            this.groupBoxPara.Text = "参数";
@@ -139,7 +139,7 @@
            this.propGrid.Location = new System.Drawing.Point(3, 17);
            this.propGrid.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
            this.propGrid.Name = "propGrid";
            this.propGrid.Size = new System.Drawing.Size(452, 497);
            this.propGrid.Size = new System.Drawing.Size(542, 497);
            this.propGrid.TabIndex = 1;
            // 
            // groupBoxCommBtn
@@ -153,7 +153,7 @@
            this.groupBoxCommBtn.Dock = System.Windows.Forms.DockStyle.Fill;
            this.groupBoxCommBtn.Location = new System.Drawing.Point(3, 3);
            this.groupBoxCommBtn.Name = "groupBoxCommBtn";
            this.groupBoxCommBtn.Size = new System.Drawing.Size(458, 114);
            this.groupBoxCommBtn.Size = new System.Drawing.Size(548, 114);
            this.groupBoxCommBtn.TabIndex = 1;
            this.groupBoxCommBtn.TabStop = false;
            this.groupBoxCommBtn.Text = "公共操作";
@@ -167,9 +167,9 @@
            this.btnStart.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.btnStart.Image = ((System.Drawing.Image)(resources.GetObject("btnStart.Image")));
            this.btnStart.ImageAlign = System.Drawing.ContentAlignment.MiddleRight;
            this.btnStart.Location = new System.Drawing.Point(309, 23);
            this.btnStart.Location = new System.Drawing.Point(374, 23);
            this.btnStart.Name = "btnStart";
            this.btnStart.Size = new System.Drawing.Size(143, 54);
            this.btnStart.Size = new System.Drawing.Size(168, 54);
            this.btnStart.TabIndex = 5;
            this.btnStart.Text = "  启  动";
            this.btnStart.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
@@ -188,7 +188,7 @@
            // 
            // buttonEmergencyStop
            // 
            this.buttonEmergencyStop.Location = new System.Drawing.Point(86, 56);
            this.buttonEmergencyStop.Location = new System.Drawing.Point(108, 56);
            this.buttonEmergencyStop.Name = "buttonEmergencyStop";
            this.buttonEmergencyStop.Size = new System.Drawing.Size(70, 25);
            this.buttonEmergencyStop.TabIndex = 4;
@@ -198,7 +198,7 @@
            // 
            // buttonServoEnable
            // 
            this.buttonServoEnable.Location = new System.Drawing.Point(86, 21);
            this.buttonServoEnable.Location = new System.Drawing.Point(108, 21);
            this.buttonServoEnable.Name = "buttonServoEnable";
            this.buttonServoEnable.Size = new System.Drawing.Size(70, 25);
            this.buttonServoEnable.TabIndex = 4;
@@ -218,7 +218,7 @@
            // 
            // buttonPositionReset
            // 
            this.buttonPositionReset.Location = new System.Drawing.Point(168, 21);
            this.buttonPositionReset.Location = new System.Drawing.Point(213, 21);
            this.buttonPositionReset.Name = "buttonPositionReset";
            this.buttonPositionReset.Size = new System.Drawing.Size(70, 25);
            this.buttonPositionReset.TabIndex = 4;
@@ -230,9 +230,10 @@
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(484, 681);
            this.ClientSize = new System.Drawing.Size(574, 681);
            this.Controls.Add(this.tableLayoutPanel1);
            this.Name = "FrmMotionCardOperationBase";
            this.Text = "板卡操作";
            this.tableLayoutPanel1.ResumeLayout(false);
            this.tabControl1.ResumeLayout(false);
            this.tabPage1.ResumeLayout(false);
src/Bro.UI.Device.Winform/MotionCard/FrmMotionCardOperationBase.cs
@@ -40,7 +40,7 @@
            foreach (var axisConfig in MotionCard.IConfig.AxisSettings.FindAll(u => u.IsAxisEnabled))
            {
                CtrlMotionCardAxisOperation axisOperation = new CtrlMotionCardAxisOperation(Device, axisConfig.AxisIndex, axisConfig.AxisName);
                axisOperation.Dock = DockStyle.Fill;
                //axisOperation.Dock = DockStyle.Fill;
                flowLayoutPanel1.Controls.Add(axisOperation);
            }