From e3868d4d61ded0e76fc8fe3fdacdd9e6d9113cf1 Mon Sep 17 00:00:00 2001
From: alielie <alielie@git.com>
Date: 星期一, 13 十月 2025 08:50:15 +0800
Subject: [PATCH] 优化HMI;

---
 HMI.ParameterManage/ParameterModal.xaml.cs     |    7 
 HMI.ParameterManage/ParameterManage.xaml.cs    |    2 
 Plugin.DataBoard/Libs/Static/test.html         |  244 +++++++++++++++
 HMI.ParameterManage/Model/XmlModel.cs          |    3 
 Plugin.DataBoard/DataBoard.xaml.cs             |  413 +++++++++++++++++----------
 HMI.ParameterManage/ParameterModal.xaml        |    3 
 SimpleUtil/HMI.Simple.Util/ParameterUtil.cs    |   18 
 HMI.ParameterManage/SettingModal.xaml.cs       |    2 
 HMI.ParameterManage/Properties/AssemblyInfo.cs |    2 
 Plugin.TsExecution/TsExecution.xaml.cs         |   85 ++---
 SimpleUtil/HMI.Simple.Util/ProductUtil.cs      |   18 +
 HMI.UnitTest/MainWindow.xaml.cs                |   91 ++++++
 12 files changed, 663 insertions(+), 225 deletions(-)

diff --git a/HMI.ParameterManage/Model/XmlModel.cs b/HMI.ParameterManage/Model/XmlModel.cs
index 16503c0..9f0f984 100644
--- a/HMI.ParameterManage/Model/XmlModel.cs
+++ b/HMI.ParameterManage/Model/XmlModel.cs
@@ -53,6 +53,8 @@
             }
         }
 
+        public List<string> groups { get; private set; }
+
         public bool ValidateProductName(object value, out string msg)
         {
             msg = null;
@@ -98,6 +100,7 @@
             }
             parameters = parameters ?? new ObservableCollection<ParameterData>();
             Parameters = parameters;
+            groups = Parameters.Where(p => !string.IsNullOrEmpty(p.PGroup)).Select(p => p.PGroup).Distinct().ToList();
         }
 
         public void SaveOrUpdateData(ProductData data)
diff --git a/HMI.ParameterManage/ParameterManage.xaml.cs b/HMI.ParameterManage/ParameterManage.xaml.cs
index 398bd8b..52ed3f5 100644
--- a/HMI.ParameterManage/ParameterManage.xaml.cs
+++ b/HMI.ParameterManage/ParameterManage.xaml.cs
@@ -101,7 +101,7 @@
                 Title = data == null ? this.lang("Pm.Parameter.Add") : this.lang("Pm.Parameter.Edit"),
                 Owner = Window.GetWindow(this),
             };
-            if (win.Open(Model.SelectedProduct.Name, data ?? new ParameterData { ProductName = Model.SelectedProduct.Name }) == true)
+            if (win.Open(Model.SelectedProduct.Name, data ?? new ParameterData { ProductName = Model.SelectedProduct.Name }, Model.groups) == true)
             {
                 Model.LoadParameters();
             }
diff --git a/HMI.ParameterManage/ParameterModal.xaml b/HMI.ParameterManage/ParameterModal.xaml
index 2e316cb..c93342f 100644
--- a/HMI.ParameterManage/ParameterModal.xaml
+++ b/HMI.ParameterManage/ParameterModal.xaml
@@ -83,7 +83,8 @@
             <pu:FormGroup x:Name="FgPGroup" Style="{StaticResource InputFormGroupStyle}" 
 Header="{DynamicResource Pm.Parameter.Group}" 
 dp:FormGroupHelper.IsRequired="False" GroupName="MyFormGroup">
-                <TextBox x:Name="TbPGroup" Style="{StaticResource EditorTextBoxStyle}" />
+                <!--<TextBox x:Name="TbPGroup" Style="{StaticResource EditorTextBoxStyle}" />-->
+                <ComboBox x:Name="CbGroup" IsEditable="True" Style="{StaticResource FormComboxStyle}"/>
             </pu:FormGroup>
         </StackPanel>
     </Grid>
diff --git a/HMI.ParameterManage/ParameterModal.xaml.cs b/HMI.ParameterManage/ParameterModal.xaml.cs
index 854380e..ab9f77a 100644
--- a/HMI.ParameterManage/ParameterModal.xaml.cs
+++ b/HMI.ParameterManage/ParameterModal.xaml.cs
@@ -84,22 +84,23 @@
                 Data.Unit = TbUnit.Text;
                 Data.Description = TbDescription.Text;
                 Data.ProductName = TbProductName.Text;
-                Data.PGroup = TbPGroup.Text;
+                Data.PGroup = CbGroup.Text;
             }
             return flag;
         }
 
-        public bool? Open(string productName, ParameterData data)
+        public bool? Open(string productName, ParameterData data, List<string> groups)
         {
             Data = data;
             TbName.Text = Data.Name;
             CbType.SelectedValue = Data.Type;
+            CbGroup.ItemsSource = groups;
             UpdateWindow(Data.Type);
             UpdateForm(Data);
             TbUnit.Text = Data.Unit;
             TbProductName.Text = productName;
             TbDescription.Text = Data.Description;
-            TbPGroup.Text = Data.PGroup;
+            CbGroup.Text = Data.PGroup;
             return this.ShowDialog();
         }
 
diff --git a/HMI.ParameterManage/Properties/AssemblyInfo.cs b/HMI.ParameterManage/Properties/AssemblyInfo.cs
index a661fe3..c4d7356 100644
--- a/HMI.ParameterManage/Properties/AssemblyInfo.cs
+++ b/HMI.ParameterManage/Properties/AssemblyInfo.cs
@@ -49,4 +49,4 @@
 //      淇鍙�
 //
 [assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.2")]
+[assembly: AssemblyFileVersion("1.0.0.3")]
diff --git a/HMI.ParameterManage/SettingModal.xaml.cs b/HMI.ParameterManage/SettingModal.xaml.cs
index 20925c9..98f2993 100644
--- a/HMI.ParameterManage/SettingModal.xaml.cs
+++ b/HMI.ParameterManage/SettingModal.xaml.cs
@@ -102,7 +102,7 @@
             return flag;
         }
 
-        public bool? Open(ParameterData data, ObservableCollection<ParameterData> datasource,List<string> groups)
+        public bool? Open(ParameterData data, ObservableCollection<ParameterData> datasource, List<string> groups)
         {
             Datasource = datasource;
             Data = data;
diff --git a/HMI.UnitTest/MainWindow.xaml.cs b/HMI.UnitTest/MainWindow.xaml.cs
index a267a28..6378bc8 100644
--- a/HMI.UnitTest/MainWindow.xaml.cs
+++ b/HMI.UnitTest/MainWindow.xaml.cs
@@ -8,10 +8,10 @@
 using Plugin.TestResult_WPF;
 using Plugin.TsExecution;
 using System;
+using System.IO;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Windows;
-
 namespace UnitTest
 {
     /// <summary>
@@ -25,6 +25,7 @@
             ProductModelHelper.GetModelBySNR("cc123", out string model, out string msg);
             LangUtil.Load();
             InitializeComponent();
+            RebuildDb();
             //page.Children.Add(new UserControl1());
         }
 
@@ -32,6 +33,94 @@
 
         PipeClient2 client;
 
+        public string Conv(object obj)
+        {
+            if (obj == null || obj is DBNull)
+            {
+                return "NULL";
+            }
+            if (obj is DateTime dt)
+            {
+                return $"'{dt.ToString("yyyy-MM-dd HH:mm:ss")}'";
+            }
+            return $"'{obj.ToString()}'";
+        }
+
+
+        public void RebuildDb()
+        {
+            string folder = "C:\\Workspace\\VisualStudio\\WPFProject\\WPFProject\\bin\\x64\\Debug\\Config\\DataBoard";
+            var startDate = DateTime.Parse("2025-10-01");
+            var endDate = startDate.AddDays(1);
+            SqliteHelper sourceHelper = new SqliteHelper("C:\\Workspace\\VisualStudio\\WPFProject\\WPFProject\\bin\\x64\\Debug\\Config\\DataBoard\\DataLog.db");
+
+            while (endDate < DateTime.Parse("2025-10-12"))
+            {
+                string targetFile = Path.Combine(folder, $"Data_{startDate.ToString("yyyyMMdd")}.db");
+                SqliteHelper targetHelper = null;
+                if (!File.Exists(targetFile))
+                {
+                    SqliteHelper.CreateDatabase(targetFile);
+                    targetHelper = new SqliteHelper(targetFile);
+                    targetHelper.ExecuteSql(@"CREATE TABLE IF NOT EXISTS serialData (
+                    id INTEGER PRIMARY KEY AUTOINCREMENT,
+                    sn TEXT NOT NULL,
+                    model TEXT,
+                    station TEXT NOT NULL,
+                    step TEXT NOT NULL,
+                    position TEXT,
+                    limitDown TEXT,
+                    limitUp TEXT,
+                    unit TEXT,
+                    offset TEXT,
+                    value TEXT,
+                    status TEXT,
+                    finalStatus TEXT,
+                    consumeTime TEXT, 
+                    totalConsumeTime TEXT, 
+                    time DATETIME NOT NULL);");
+                    targetHelper.ExecuteSql(@"CREATE TABLE IF NOT EXISTS testResult (
+                    id INTEGER PRIMARY KEY AUTOINCREMENT,
+                    sn TEXT NOT NULL,
+                    model TEXT,
+                    station TEXT NOT NULL,
+                    position TEXT,
+                    status TEXT,
+                    result TEXT NOT NULL, 
+                    time DATETIME NOT NULL);");
+
+                    string sql = $@"SELECT sn,model,station,step,position,limitDown,limitUp,unit,offset,value,status,
+finalStatus,consumeTime,totalConsumeTime,time
+FROM serialData WHERE time>='{startDate.ToString("yyyy-MM-dd")}' AND time < '{endDate.ToString("yyyy-MM-dd")}';";
+
+                    var dt = sourceHelper.GetDataTable(sql);
+                    foreach (System.Data.DataRow dr in dt.Rows)
+                    {
+                        targetHelper.ExecuteSql($@"INSERT INTO serialData 
+(sn,model,station,step,position,limitDown,limitUp,unit,offset,value,status,finalStatus,consumeTime,totalConsumeTime,time) VALUES
+({Conv(dr["sn"])}, {Conv(dr["model"])}, {Conv(dr["station"])}, {Conv(dr["step"])}, {Conv(dr["position"])}, {Conv(dr["limitDown"])}, {Conv(dr["limitUP"])},
+{Conv(dr["unit"])}, {Conv(dr["offset"])}, {Conv(dr["value"])}, {Conv(dr["status"])}, {Conv(dr["finalStatus"])}, {Conv(dr["consumeTime"])}, 
+{Conv(dr["totalConsumeTime"])}, {Conv(dr["time"])})");
+                    }
+                    sql = $@"SELECT sn,model,station,position,status,result,time FROM testResult WHERE time>='{startDate.ToString("yyyy-MM-dd")}' 
+AND time < '{endDate.ToString("yyyy-MM-dd")}';";
+
+                    dt = sourceHelper.GetDataTable(sql);
+                    foreach (System.Data.DataRow dr in dt.Rows)
+                    {
+                        targetHelper.ExecuteSql($@"INSERT INTO testResult 
+(sn,model,station,position,status,result,time) VALUES
+({Conv(dr["sn"])}, {Conv(dr["model"])}, {Conv(dr["station"])}, {Conv(dr["position"])}, {Conv(dr["status"])}, {Conv(dr["result"])}, {Conv(dr["time"])})");
+                    }
+
+                    targetHelper.Dispose();
+                    startDate = startDate.AddDays(1);
+                    endDate = endDate.AddDays(1);
+                }
+            }
+            sourceHelper.Dispose();
+        }
+
         private void Button_Click(object sender, RoutedEventArgs e)
         {
             Task.Run(() =>
diff --git a/Plugin.DataBoard/DataBoard.xaml.cs b/Plugin.DataBoard/DataBoard.xaml.cs
index 57aa86f..7e66211 100644
--- a/Plugin.DataBoard/DataBoard.xaml.cs
+++ b/Plugin.DataBoard/DataBoard.xaml.cs
@@ -10,6 +10,7 @@
 using System.Drawing;
 using System.IO;
 using System.Linq;
+using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Controls;
 
@@ -76,14 +77,37 @@
             }
         }
 
+        public static string[] GetDbFiles(string folderPath, DateTime startTime, DateTime endTime)
+        {
+            if (!Directory.Exists(folderPath))
+            {
+                return new string[0];
+            }
+            string startName = $"Data_{startTime.ToString("yyyyMMdd")}";
+            string endName = $"Data_{endTime.ToString("yyyyMMdd")}";
+            var oldFiles = Directory.GetFiles(folderPath, "Data_*.db");
+            oldFiles = oldFiles.Where(file =>
+            {
+                var fileName = Path.GetFileNameWithoutExtension(file);
+                bool flag = true;
+                if (startTime != null) flag &= (string.Compare(fileName, startName) == 1 || fileName == startName);
+                if (endTime != null) flag &= (string.Compare(endName, fileName) == 1 || fileName == endName);
+                return flag;
+            }).ToArray();
+
+            return oldFiles;
+        }
+
+
         private List<SerialData> SelectSerialDataByTime(DateTime start, DateTime end)
         {
-            string[] files = DbFileHelper.GetDbFiles(BaseFolder, start, end);
+            var s1 = DateTime.Now;
+            string[] files = GetDbFiles(BaseFolder, start, end);
             if (files == null || files.Length <= 0)
             {
                 return new List<SerialData>();
             }
-            string sql = $"SELECT * FROM serialData WHERE time BETWEEN '{start:yyyy-MM-dd HH:mm:ss}' AND '{end:yyyy-MM-dd HH:mm:ss}';";
+            string sql = $"SELECT * FROM serialData WHERE time BETWEEN '{start:yyyy-MM-dd HH:mm:ss}' AND '{end:yyyy-MM-dd HH:mm:ss}' ORDER BY time DESC;";
 
             DataTable dt = new DataTable();
             foreach (string file in files)
@@ -93,12 +117,16 @@
                     dt.Merge(helper.GetDataTable(sql));
                 }
             }
-            return BeanUtil.ReadBeanFromDataTable<SerialData>(dt);
+            var s2 = DateTime.Now;
+            log.Info($"SelectSerialDataByTime Cast: {(s2 - s1).TotalMilliseconds}");
+            var data = BeanUtil.ReadBeanFromDataTable<SerialData>(dt);
+            log.Info($"Bean Cast: {(DateTime.Now - s2).TotalMilliseconds}");
+            return data;
         }
 
         private List<SerialData> SelectResultDataByTime(DateTime start, DateTime end)
         {
-            string[] files = DbFileHelper.GetDbFiles(BaseFolder, start, end);
+            string[] files = GetDbFiles(BaseFolder, start, end);
             if (files == null || files.Length <= 0)
             {
                 return new List<SerialData>();
@@ -110,7 +138,8 @@
             {
                 using (SqliteHelper helper = new SqliteHelper(file))
                 {
-                    dt.Merge(helper.GetDataTable(sql));
+                    var temp = helper.GetDataTable(sql);
+                    dt.Merge(temp);
                 }
             }
             return BeanUtil.ReadBeanFromDataTable<SerialData>(dt);
@@ -137,81 +166,135 @@
             webview2.CoreWebView2?.ExecuteScriptAsync($"resize({width},{height})");
         }
 
+        //private void RefreshChart0(DateTime start, DateTime end)
+        //{
+        //    dtp00.SelectedDateTime = start;
+        //    dtp01.SelectedDateTime = end;
+        //    Task.Run(() =>
+        //    {
+        //        try
+        //        {
+        //            var st = DateTime.Now;
+        //            List<SerialData> datas = SelectSerialDataByTime(start, end);
+        //            log.Info($"0 Select Data cast: {(DateTime.Now-st).TotalMilliseconds}");
+
+        //            datas.OrderByDescending(e => e.time);
+        //            int all = 0, output = 0;
+        //            HashSet<string> snCache = new HashSet<string>();
+        //            foreach (var data in datas)
+        //            {
+        //                if (snCache.Contains(data.sn)) continue;
+        //                snCache.Add(data.sn);
+        //                all++;
+        //                if (data.status == "Passed") output++;
+        //            }
+        //            var fields = $"['{this.lang("bd.input")}','{this.lang("bd.output")}']";
+        //            Dispatcher.BeginInvoke(new Action(() =>
+        //            {
+        //                webview2.CoreWebView2?.ExecuteScriptAsync($"drawChart0({fields}, [{all},{output}])");
+        //            }));
+        //        }
+        //        catch (Exception ex)
+        //        {
+        //            log.Error("RefreshChart0 Error.", ex);
+        //            ToastHelper.Error("琛�1鍒锋柊澶辫触锛�");
+        //        }
+        //    });
+        //}
+
         private void RefreshChart0(DateTime start, DateTime end)
         {
-            try
+            dtp00.SelectedDateTime = start;
+            dtp01.SelectedDateTime = end;
+            Task.Run(() =>
             {
-                dtp00.SelectedDateTime = start;
-                dtp01.SelectedDateTime = end;
-                List<SerialData> datas = SelectSerialDataByTime(start, end);
-
-                datas.OrderByDescending(e => e.time);
-                int all = 0, output = 0;
-                HashSet<string> snCache = new HashSet<string>();
-                foreach (var data in datas)
+                try
                 {
-                    if (snCache.Contains(data.sn)) continue;
-                    snCache.Add(data.sn);
-                    all++;
-                    if (data.status == "Passed") output++;
+                    Dispatcher.BeginInvoke(new Action(() =>
+                    {
+                        webview2.CoreWebView2?.ExecuteScriptAsync($"loading0('鍔犺浇涓紝璇风◢鍚�...')");
+                    }));
+                    List<SerialData> datas = SelectResultDataByTime(start, end);
+                    datas.OrderByDescending(e => e.time);
+                    int all = 0, output = 0;
+                    HashSet<string> snCache = new HashSet<string>();
+                    foreach (var data in datas)
+                    {
+                        if (snCache.Contains(data.sn)) continue;
+                        snCache.Add(data.sn);
+                        all++;
+                        if (data.result == "Passed") output++;
+                    }
+                    var fields = $"['{this.lang("bd.input")}','{this.lang("bd.output")}']";
+                    Dispatcher.BeginInvoke(new Action(() =>
+                    {
+                        webview2.CoreWebView2?.ExecuteScriptAsync($"drawChart0({fields}, [{all},{output}])");
+                    }));
                 }
-                var fields = $"['{this.lang("bd.input")}','{this.lang("bd.output")}']";
-
-                webview2.CoreWebView2?.ExecuteScriptAsync($"drawChart0({fields}, [{all},{output}])");
-            }
-            catch (Exception ex)
-            {
-                log.Error("RefreshChart0 Error.", ex);
-                ToastHelper.Error("琛�1鍒锋柊澶辫触锛�");
-            }
+                catch (Exception ex)
+                {
+                    log.Error("RefreshChart0 Error.", ex);
+                    ToastHelper.Error("琛�1鍒锋柊澶辫触锛�");
+                }
+            });
         }
 
         private void RefreshChart1(DateTime start, DateTime end)
         {
-            try
+            dtp10.SelectedDateTime = start;
+            dtp11.SelectedDateTime = end;
+            Task.Run(() =>
             {
-                dtp10.SelectedDateTime = start;
-                dtp11.SelectedDateTime = end;
-                List<SerialData> datas = SelectResultDataByTime(start, end);
+                try
+                {
+                    Dispatcher.BeginInvoke(new Action(() =>
+                    {
+                        webview2.CoreWebView2?.ExecuteScriptAsync($"loading1('鍔犺浇涓紝璇风◢鍚�...')");
+                    }));
+                    List<SerialData> datas = SelectResultDataByTime(start, end);
 
-                datas = datas.OrderByDescending(e => e.time).ToList();
-                Dictionary<string, int?> pieData = new Dictionary<string, int?> {
+                    datas = datas.OrderByDescending(e => e.time).ToList();
+                    Dictionary<string, int?> pieData = new Dictionary<string, int?> {
                 { "Passed",0},
                 { "Failed",0},
                 //{ "Action",0},
                 //{ "Wait",0},
             };
-                //if (datas == null || datas.Count <= 0)
-                //{
-                //    pieData = new Dictionary<string, int?> {
-                //    { "Passed",null},
-                //    { "Failed",null},
-                //};
-                //}
+                    //if (datas == null || datas.Count <= 0)
+                    //{
+                    //    pieData = new Dictionary<string, int?> {
+                    //    { "Passed",null},
+                    //    { "Failed",null},
+                    //};
+                    //}
 
-                HashSet<string> snCache = new HashSet<string>();
-                foreach (var data in datas)
-                {
-                    if (snCache.Contains(data.sn)) continue;
-                    snCache.Add(data.sn);
-                    if (pieData.ContainsKey(data.result))
+                    HashSet<string> snCache = new HashSet<string>();
+                    foreach (var data in datas)
                     {
-                        pieData[data.result]++;
+                        if (snCache.Contains(data.sn)) continue;
+                        snCache.Add(data.sn);
+                        if (pieData.ContainsKey(data.result))
+                        {
+                            pieData[data.result]++;
+                        }
                     }
+                    string res = "[";
+                    foreach (var key in pieData.Keys)
+                    {
+                        res += $"{{name:'{key}',value:{pieData[key]}}},";
+                    }
+                    res += "]";
+                    Dispatcher.BeginInvoke(new Action(() =>
+                    {
+                        webview2.CoreWebView2?.ExecuteScriptAsync($"drawChart1({res})");
+                    }));
                 }
-                string res = "[";
-                foreach (var key in pieData.Keys)
+                catch (Exception ex)
                 {
-                    res += $"{{name:'{key}',value:{pieData[key]}}},";
+                    log.Error("RefreshChart1 Error.", ex);
+                    ToastHelper.Error("琛�2鍒锋柊澶辫触锛�");
                 }
-                res += "]";
-                webview2.CoreWebView2?.ExecuteScriptAsync($"drawChart1({res})");
-            }
-            catch (Exception ex)
-            {
-                log.Error("RefreshChart1 Error.", ex);
-                ToastHelper.Error("琛�2鍒锋柊澶辫触锛�");
-            }
+            });
         }
 
         //private void RefreshChart2(DateTime start, DateTime end)
@@ -282,129 +365,147 @@
 
         private void RefreshChart2(DateTime start, DateTime end)
         {
-            try
+            dtp20.SelectedDateTime = start;
+            dtp21.SelectedDateTime = end;
+            Task.Run(() =>
             {
-                dtp20.SelectedDateTime = start;
-                dtp21.SelectedDateTime = end;
-                List<SerialData> datas = SelectResultDataByTime(start, end);
-
-                var groups =
-                    datas.GroupBy(d => d.time.ToString("yyyy-MM-dd"));
-
-                Dictionary<string, PassRateData> res = new Dictionary<string, PassRateData>();
-
-                foreach (var group in groups)
+                try
                 {
-                    Dictionary<string, string> snStatusCache = new Dictionary<string, string>();
-                    double all = 0, oneTimePass = 0, passed = 0;
-                    var groupDatas = group.ToList();
-                    groupDatas = groupDatas.OrderByDescending(e => e.time).ToList();
-
-                    foreach (var data in groupDatas)
+                    Dispatcher.BeginInvoke(new Action(() =>
                     {
-                        if (!snStatusCache.ContainsKey(data.sn))
+                        webview2.CoreWebView2?.ExecuteScriptAsync($"loading2('鍔犺浇涓紝璇风◢鍚�...')");
+                    }));
+                    List<SerialData> datas = SelectResultDataByTime(start, end);
+
+                    var groups =
+                        datas.GroupBy(d => d.time.ToString("yyyy-MM-dd"));
+
+                    Dictionary<string, PassRateData> res = new Dictionary<string, PassRateData>();
+
+                    foreach (var group in groups)
+                    {
+                        Dictionary<string, string> snStatusCache = new Dictionary<string, string>();
+                        double all = 0, oneTimePass = 0, passed = 0;
+                        var groupDatas = group.ToList();
+                        groupDatas = groupDatas.OrderByDescending(e => e.time).ToList();
+
+                        foreach (var data in groupDatas)
                         {
-                            snStatusCache.Add(data.sn, data.result);
-                            all++;
-                            if (data.result == "Passed")
+                            if (!snStatusCache.ContainsKey(data.sn))
                             {
-                                passed++;
-                                oneTimePass++;
+                                snStatusCache.Add(data.sn, data.result);
+                                all++;
+                                if (data.result == "Passed")
+                                {
+                                    passed++;
+                                    oneTimePass++;
+                                }
+                            }
+                            else
+                            {
+                                if (snStatusCache[data.sn] == "Passed")
+                                {
+                                    if (oneTimePass > 0) oneTimePass--;
+                                    snStatusCache[data.sn] = "NoOnePass";
+                                }
                             }
                         }
-                        else
+                        res.Add(group.Key, new PassRateData
                         {
-                            if (snStatusCache[data.sn] == "Passed")
-                            {
-                                if (oneTimePass > 0) oneTimePass--;
-                                snStatusCache[data.sn] = "NoOnePass";
-                            }
-                        }
+                            time = group.Key,
+                            onePassRate = oneTimePass / all * 100,
+                            passRate = passed / all * 100,
+                        });
                     }
-                    res.Add(group.Key, new PassRateData
+
+                    string fields = "[", vals0 = "[", vals1 = "[";
+                    foreach (var key in res.Keys)
                     {
-                        time = group.Key,
-                        onePassRate = oneTimePass / all * 100,
-                        passRate = passed / all * 100,
-                    });
+                        fields += $"'{key}',";
+                        vals0 += $"{res[key].onePassRate},";
+                        vals1 += $"{res[key].passRate},";
+                    }
+                    fields += "]";
+                    vals0 += "]";
+                    vals1 += "]";
+                    var names = $"['{this.lang("bd.onePassRate")}','{this.lang("bd.passRate")}']";
+                    Dispatcher.BeginInvoke(new Action(() =>
+                    {
+                        webview2.CoreWebView2?.ExecuteScriptAsync($"drawChart2({fields},{names},{vals0},{vals1})");
+                    }));
                 }
-
-
-
-                string fields = "[", vals0 = "[", vals1 = "[";
-                foreach (var key in res.Keys)
+                catch (Exception ex)
                 {
-                    fields += $"'{key}',";
-                    vals0 += $"{res[key].onePassRate},";
-                    vals1 += $"{res[key].passRate},";
+                    log.Error("RefreshChart2 Error.", ex);
+                    ToastHelper.Error("琛�3鍒锋柊澶辫触锛�");
                 }
-                fields += "]";
-                vals0 += "]";
-                vals1 += "]";
-                var names = $"['{this.lang("bd.onePassRate")}','{this.lang("bd.passRate")}']";
-                webview2.CoreWebView2?.ExecuteScriptAsync($"drawChart2({fields},{names},{vals0},{vals1})");
-            }
-            catch (Exception ex)
-            {
-                log.Error("RefreshChart2 Error.", ex);
-                ToastHelper.Error("琛�3鍒锋柊澶辫触锛�");
-            }
+            });
         }
 
         private void RefreshChart3(DateTime start, DateTime end)
         {
-            try
+            dtp30.SelectedDateTime = start;
+            dtp31.SelectedDateTime = end;
+            Task.Run(() =>
             {
-                dtp30.SelectedDateTime = start;
-                dtp31.SelectedDateTime = end;
-                List<SerialData> datas = SelectSerialDataByTime(start, end);
-
-                datas = datas.OrderByDescending(e => e.time).ToList();
-
-
-
-                Dictionary<string, SimpleData> pieData = new Dictionary<string, SimpleData>();
-                List<SimpleData> datasource = new List<SimpleData>();
-                //HashSet<string> snCache = new HashSet<string>();
-
-                foreach (var data in datas)
+                try
                 {
-                    //if (snCache.Contains(data.sn)) continue;
-                    if (data.status != "Failed") continue;
-                    if (pieData.ContainsKey(data.step))
+                    Dispatcher.BeginInvoke(new Action(() =>
                     {
-                        pieData[data.step].Value++;
-                    }
-                    else
+                        webview2.CoreWebView2?.ExecuteScriptAsync($"loading3('鍔犺浇涓紝璇风◢鍚�...')");
+                    }));
+                    var st = DateTime.Now;
+                    List<SerialData> datas = SelectSerialDataByTime(start, end);
+                    var s2 = DateTime.Now;
+                    log.Info($"RefreshChart3 Data Cast {(s2 - st).TotalMilliseconds}");
+
+                    Dictionary<string, SimpleData> pieData = new Dictionary<string, SimpleData>();
+                    List<SimpleData> datasource = new List<SimpleData>();
+                    //HashSet<string> snCache = new HashSet<string>();
+
+                    foreach (var data in datas)
                     {
-                        pieData[data.step] = new SimpleData
+                        //if (snCache.Contains(data.sn)) continue;
+                        if (data.status != "Failed") continue;
+                        if (pieData.ContainsKey(data.step))
                         {
-                            Name = data.step,
-                            Value = 1
-                        };
-                        datasource.Add(pieData[data.step]);
+                            pieData[data.step].Value++;
+                        }
+                        else
+                        {
+                            pieData[data.step] = new SimpleData
+                            {
+                                Name = data.step,
+                                Value = 1
+                            };
+                            datasource.Add(pieData[data.step]);
+                        }
                     }
-                }
-                datasource = datasource.OrderByDescending(e => e.Value).ToList();
-                if (datasource.Count > 10)
-                {
-                    datasource = datasource.Take(10).ToList();
-                }
+                    datasource = datasource.OrderByDescending(e => e.Value).ToList();
+                    if (datasource.Count > 10)
+                    {
+                        datasource = datasource.Take(10).ToList();
+                    }
+                    var s3 = DateTime.Now;
+                    log.Info($"RefreshChart3 Build {(s3 - s2).TotalMilliseconds}");
 
-                string names = string.Empty, vals = string.Empty;
-                foreach (var data in datasource)
-                {
-                    names += $"'{data.Name}',";
-                    vals += $"{data.Value},";
+                    string names = string.Empty, vals = string.Empty;
+                    foreach (var data in datasource)
+                    {
+                        names += $"'{data.Name}',";
+                        vals += $"{data.Value},";
+                    }
+                    Dispatcher.BeginInvoke(new Action(() =>
+                    {
+                        webview2.CoreWebView2?.ExecuteScriptAsync($"drawChart3([{names}],[{vals}])");
+                    }));
                 }
-
-                webview2.CoreWebView2?.ExecuteScriptAsync($"drawChart3([{names}],[{vals}])");
-            }
-            catch (Exception ex)
-            {
-                log.Error("RefreshChart3 Error.", ex);
-                ToastHelper.Error("琛�4鍒锋柊澶辫触锛�");
-            }
+                catch (Exception ex)
+                {
+                    log.Error("RefreshChart3 Error.", ex);
+                    ToastHelper.Error("琛�4鍒锋柊澶辫触锛�");
+                }
+            });
         }
 
         private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
diff --git a/Plugin.DataBoard/Libs/Static/test.html b/Plugin.DataBoard/Libs/Static/test.html
index 9b2e204..2989317 100644
--- a/Plugin.DataBoard/Libs/Static/test.html
+++ b/Plugin.DataBoard/Libs/Static/test.html
@@ -6,6 +6,140 @@
 <head>
     <title>Simple Surface</title>
     <meta charset="utf-8">
+    <style type="text/css">
+        /* 瀵� loading  鏁翠綋甯冨眬*/
+        .loading-wrapper {
+            padding: 16px;
+            background-color: rgba(0, 0, 0, 0.8);
+            border-radius: 10px;
+            color: #fff;
+            text-align: center;
+            display: flex;
+            flex-direction: column;
+            justify-content: space-evenly;
+            position: absolute;
+            left: 50%;
+            top: 50%;
+            transform: translate(-50%, -50%);
+            background: rgba(0, 0, 0, 0.5);
+        }
+
+
+        /* loading 鍔ㄧ敾鍥惧儚鐖剁骇鐨勫竷灞� */
+        .loading-view {
+            height: 40px;
+            position: relative;
+        }
+
+        .loading-msg {
+            font-size: 14px;
+            margin: 8px 0 0 0;
+            position: relative;
+        }
+
+        .container1,
+        .container2 {
+            width: 40px;
+            height: 40px;
+            position: absolute;
+            /* border: 1px solid #ff0000; */
+            top: 0;
+            left: 50%;
+            margin-left: -20px;
+            position: absolute;
+        }
+
+        .container2 {
+            transform: rotate(45deg);
+        }
+
+        /* 绗�1绉嶅姩鐢诲拰绗簩绉嶇殑鐩稿悓閮ㄥ垎锛屽叾涓殑 animation 涔熺浉鍚� */
+        .circle,
+        .bounce {
+            width: 10px;
+            height: 10px;
+            background-color: #fff;
+            border-radius: 50%;
+            /* 璁剧疆灏忕悆鍔ㄧ敾 */
+            animation: loading 1.2s both infinite;
+        }
+
+        .circle {
+            position: absolute;
+        }
+
+        /* 璁剧疆灏忕悆鐨勭浉瀵逛綅缃� */
+        .circle1 {
+            top: 0;
+            left: 0;
+        }
+
+        .circle2 {
+            top: 0;
+            right: 0;
+        }
+
+        .circle3 {
+            bottom: 0;
+            right: 0;
+        }
+
+        .circle4 {
+            bottom: 0;
+            left: 0;
+        }
+
+        /* 璁剧疆寤舵椂 */
+        .container1 .circle1 {
+            animation-delay: 0s;
+        }
+
+        .container2 .circle1 {
+            animation-delay: 0.2s;
+        }
+
+        .container1 .circle2 {
+            animation-delay: 0.3s;
+        }
+
+        .container2 .circle2 {
+            animation-delay: 0.4s;
+        }
+
+        .container1 .circle3 {
+            animation-delay: 0.5s;
+        }
+
+        .container2 .circle3 {
+            animation-delay: 0.6s;
+        }
+
+        .container1 .circle4 {
+            animation-delay: 0.7s;
+        }
+
+        .container2 .circle5 {
+            animation-delay: 0.8s;
+        }
+
+        @keyframes loading {
+            0% {
+                transform: scale(0);
+            }
+
+            40% {
+                transform: scale(1);
+            }
+
+            80% {
+                transform: scale(0);
+            }
+
+            100% {
+                transform: scale(0);
+            }
+        }
+    </style>
     <script src="echarts.min.js"></script>
     <script type="text/javascript">
         const color = ['#22448b'];
@@ -37,12 +171,15 @@
         .chart {
             height: 100%;
             width: 25%;
+            position: relative;
         }
     </style>
 </head>
 <body>
     <div id="container">
-        <div id="chart0" class="chart"></div>
+        <div id="chart0" class="chart">
+            
+        </div>
         <div id="chart1" class="chart"></div>
         <div id="chart2" class="chart"></div>
         <div id="chart3" class="chart"></div>
@@ -75,9 +212,33 @@
                 }
             ]
         };
-        var chart0 = echarts.init(dom0);
+        var chart0 = null;
+        function loading0(msg) {
+            if (chart0 != null) {
+                chart0.dispose();
+                chart0 = null;
+            }
+            dom0.innerHTML = `<div class="loading-wrapper">
+    <div class="loading-view">
+        <div class="container1">
+            <div class="circle circle1"></div>
+            <div class="circle circle2"></div>
+            <div class="circle circle3"></div>
+            <div class="circle circle4"></div>
+        </div>
+        <div class="container2">
+            <div class="circle circle1"></div>
+            <div class="circle circle2"></div>
+            <div class="circle circle3"></div>
+            <div class="circle circle4"></div>
+        </div>
+    </div>
+    <h2 class="loading-msg">${msg}</h2>
+</div>`
+        }
 
         function drawChart0(fields, data) {
+            chart0 = echarts.init(dom0);
             opt0.xAxis.data = fields;
             opt0.series[0].data = data;
             chart0.setOption(opt0);
@@ -125,9 +286,33 @@
                 }
             ]
         };
-        var chart1 = echarts.init(dom1);
+        var chart1 = null;
+        function loading1(msg) {
+            if (chart1 != null) {
+                chart1.dispose();
+                chart1 = null;
+            }
+            dom1.innerHTML = `<div class="loading-wrapper">
+    <div class="loading-view">
+        <div class="container1">
+            <div class="circle circle1"></div>
+            <div class="circle circle2"></div>
+            <div class="circle circle3"></div>
+            <div class="circle circle4"></div>
+        </div>
+        <div class="container2">
+            <div class="circle circle1"></div>
+            <div class="circle circle2"></div>
+            <div class="circle circle3"></div>
+            <div class="circle circle4"></div>
+        </div>
+    </div>
+    <h2 class="loading-msg">${msg}</h2>
+</div>`
+        }
 
         function drawChart1(data) {
+            chart1 = echarts.init(dom1);
             opt1.series[0].data = data;
             chart1.setOption(opt1);
         }
@@ -175,9 +360,33 @@
                 }
             ]
         };
-        var chart2 = echarts.init(dom2);
+        var chart2 = null;
+        function loading2(msg) {
+            if (chart2 != null) {
+                chart2.dispose();
+                chart2 = null;
+            }
+            dom2.innerHTML = `<div class="loading-wrapper">
+    <div class="loading-view">
+        <div class="container1">
+            <div class="circle circle1"></div>
+            <div class="circle circle2"></div>
+            <div class="circle circle3"></div>
+            <div class="circle circle4"></div>
+        </div>
+        <div class="container2">
+            <div class="circle circle1"></div>
+            <div class="circle circle2"></div>
+            <div class="circle circle3"></div>
+            <div class="circle circle4"></div>
+        </div>
+    </div>
+    <h2 class="loading-msg">${msg}</h2>
+</div>`
+        }
 
         function drawChart2(label, names, data0, data1) {
+            chart2 = echarts.init(dom2)
             opt2.xAxis.data = label;
             opt2.series[0].name = names[0];
             opt2.series[0].data = data0;
@@ -242,9 +451,34 @@
                 }
             ]
         };
-        var chart3 = echarts.init(dom3);
+        var chart3 = null;
+
+        function loading3(msg) {
+            if (chart3 != null) {
+                chart3.dispose();
+                chart3 = null;
+            }
+            dom3.innerHTML = `<div class="loading-wrapper">
+    <div class="loading-view">
+        <div class="container1">
+            <div class="circle circle1"></div>
+            <div class="circle circle2"></div>
+            <div class="circle circle3"></div>
+            <div class="circle circle4"></div>
+        </div>
+        <div class="container2">
+            <div class="circle circle1"></div>
+            <div class="circle circle2"></div>
+            <div class="circle circle3"></div>
+            <div class="circle circle4"></div>
+        </div>
+    </div>
+    <h2 class="loading-msg">${msg}</h2>
+</div>`
+        }
 
         function drawChart3(label, data) {
+            chart3 = echarts.init(dom3);
             opt3.yAxis.data = label;
             opt3.series[0].data = data;
             chart3.setOption(opt3);
diff --git a/Plugin.TsExecution/TsExecution.xaml.cs b/Plugin.TsExecution/TsExecution.xaml.cs
index 83c45f0..11614c4 100644
--- a/Plugin.TsExecution/TsExecution.xaml.cs
+++ b/Plugin.TsExecution/TsExecution.xaml.cs
@@ -263,6 +263,7 @@
             }
         }
 
+        private string tsModelPath;
         private string dataLogPath;
         private SqliteHelper sqliteHelper;
 
@@ -284,23 +285,25 @@
             base.SetBaseFolder(folder);
         }
 
-        public override void InitFinish()
+        private void CheckSqlHelper()
         {
-            this.ReadCount(out int pass, out int fail);
-            this.DisplayCount(pass, fail);
-            InitProducts();
-            ReadConfig();
-            if (!File.Exists(dataLogPath))
+            string today = DateTime.Now.ToString("yyyyMMdd");
+            string dbPath = Path.Combine(dataLogPath, $"Data_{today}.db");
+            if (!File.Exists(dbPath))
             {
-                SqliteHelper.CreateDatabase(dataLogPath);
+                SqliteHelper.CreateDatabase(dbPath);
             }
-            sqliteHelper = new SqliteHelper(dataLogPath);
-            sqliteHelper.ExecuteSql(@"CREATE TABLE IF NOT EXISTS serialData (
+            if (sqliteHelper == null || sqliteHelper.DataBaseFile != dbPath)
+            {
+                sqliteHelper?.Dispose();
+                sqliteHelper = new SqliteHelper(dbPath);
+                sqliteHelper.ExecuteSql(@"CREATE TABLE IF NOT EXISTS serialData (
                     id INTEGER PRIMARY KEY AUTOINCREMENT,
                     sn TEXT NOT NULL,
                     model TEXT,
                     station TEXT NOT NULL,
                     step TEXT NOT NULL,
+                    position TEXT,
                     limitDown TEXT,
                     limitUp TEXT,
                     unit TEXT,
@@ -311,48 +314,25 @@
                     consumeTime TEXT, 
                     totalConsumeTime TEXT, 
                     time DATETIME NOT NULL);");
-            sqliteHelper.ExecuteSql(@"CREATE TABLE IF NOT EXISTS testResult (
+                sqliteHelper.ExecuteSql(@"CREATE TABLE IF NOT EXISTS testResult (
                     id INTEGER PRIMARY KEY AUTOINCREMENT,
                     sn TEXT NOT NULL,
                     model TEXT,
                     station TEXT NOT NULL,
+                    position TEXT,
+                    status TEXT,
                     result TEXT NOT NULL, 
                     time DATETIME NOT NULL);");
-            try
-            {
-                sqliteHelper.ExecuteSql("alter table serialData add column 'model' TEXT default NULL;");
             }
-            catch
-            {
+        }
 
-            }
-
-            try
-            {
-                sqliteHelper.ExecuteSql("alter table serialData add column 'position' TEXT default NULL;");
-            }
-            catch
-            {
-
-            }
-            try
-            {
-                sqliteHelper.ExecuteSql("alter table testResult add column 'position' TEXT default NULL;");
-            }
-            catch
-            {
-
-            }
-
-            try
-            {
-                sqliteHelper.ExecuteSql("alter table testResult add column 'status' TEXT default NULL;");
-            }
-            catch
-            {
-
-            }
-
+        public override void InitFinish()
+        {
+            this.ReadCount(out int pass, out int fail);
+            this.DisplayCount(pass, fail);
+            InitProducts();
+            ReadConfig();
+            CheckSqlHelper();
             base.InitFinish();
         }
 
@@ -865,8 +845,21 @@
             }
             catch
             {
-                dataLogPath = Path.Combine(PathHelper.ConfigFolder, "DataBoard", "DataLog.db");
+                dataLogPath = Path.Combine(PathHelper.ConfigFolder, "DataBoard");
             }
+
+            try
+            {
+
+                value = ParameterManager.GetCommonParameterByName("TsModelPath");
+                tsModelPath = value.Value;
+            }
+            catch
+            {
+                //@"C:\Program Files\National Instruments\TestStand 2020\Components\Models\TestStandModels\ParallelModel.seq"
+                tsModelPath = @"C:\Users\Public\Documents\National Instruments\TestStand 2020 (64-bit)\Components\Models\ParallelModel.seq";
+            }
+
 
             //Convert.ToBoolean(IniFileHelper.ReadIniData("Config", "EnableMes", "true", CountIniPath));
             //EnableCanLog = Convert.ToBoolean(IniFileHelper.ReadIniData("Config", "EnableCanLog", "true", CountIniPath));
@@ -1001,8 +994,7 @@
             {
                 engine?.Globals.SetValString("StationState.ProductModel", 1, SelectedProduct?.Name);
                 engine?.CommitGlobalsToDisk(promptOnSaveConflicts: false);
-                //this.modeSeq = this.engine.GetSequenceFileEx(@"C:\Program Files\National Instruments\TestStand 2020\Components\Models\TestStandModels\ParallelModel.seq");
-                this.modeSeq = this.engine.GetSequenceFileEx(@"C:\Users\Public\Documents\National Instruments\TestStand 2020 (64-bit)\Components\Models\ParallelModel.seq");
+                this.modeSeq = this.engine.GetSequenceFileEx(tsModelPath);
                 this.testSeq = this.engine.GetSequenceFileEx(this.testSeqFile, 2, TypeConflictHandlerTypes.ConflictHandler_UseGlobalType);
                 this.execution = this.engine.NewExecution(this.testSeq, "Test UUTs", this.modeSeq, false, 0, null, null, null);
                 IsTesting = true;
@@ -1180,6 +1172,7 @@
 
         public void SavePositionDB(int index, string status)
         {
+            CheckSqlHelper();
             var socket = this.tsSockets[index];
             var time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
             string snr = socket.Barcode;
diff --git a/SimpleUtil/HMI.Simple.Util/ParameterUtil.cs b/SimpleUtil/HMI.Simple.Util/ParameterUtil.cs
index 25b24ae..ae461c2 100644
--- a/SimpleUtil/HMI.Simple.Util/ParameterUtil.cs
+++ b/SimpleUtil/HMI.Simple.Util/ParameterUtil.cs
@@ -9,11 +9,11 @@
     public class ParameterUtil
     {
         /// <summary>
-        /// 
+        /// 鏍规嵁璺緞鍜屽弬鏁板悕鑾峰彇鍙傛暟鍊�
         /// </summary>
-        /// <param name="path"></param>
-        /// <param name="name"></param>
-        /// <returns></returns>
+        /// <param name="path">璺緞</param>
+        /// <param name="name">鍙傛暟鍚�</param>
+        /// <returns>鍙傛暟鍊�</returns>
         public static string GetCommonParameterValue(string path, string name)
         {
             if (!File.Exists(path)) return null;
@@ -26,8 +26,8 @@
         /// <summary>
         /// 鑾峰彇HMI閲岄厤缃殑鍙傛暟
         /// </summary>
-        /// <param name="name"></param>
-        /// <returns></returns>
+        /// <param name="name">鍙傛暟鍚�</param>
+        /// <returns>鍙傛暟鍊�</returns>
         public static string GetCommonParameterValue(string name, out string errMsg)
         {
             errMsg = string.Empty;
@@ -101,8 +101,10 @@
         /// <summary>
         /// 灏嗗弬鏁板啓杩汦ngine鐨凷tationGlobals.StationState
         /// </summary>
-        /// <param name="name"></param>
-        /// <returns></returns>
+        /// <param name="xmlPath">缁濆璺緞</param>
+        /// <param name="instance">TestStand涓婁笅鏂�</param>
+        /// <param name="errMsg">寮傚父淇℃伅</param>
+        /// <returns>鏄惁鎴愬姛</returns>
         public static bool WriteConfigToContext(string xmlPath, object instance, out string errMsg)
         {
             errMsg = string.Empty;
diff --git a/SimpleUtil/HMI.Simple.Util/ProductUtil.cs b/SimpleUtil/HMI.Simple.Util/ProductUtil.cs
index aab00f6..a6969e3 100644
--- a/SimpleUtil/HMI.Simple.Util/ProductUtil.cs
+++ b/SimpleUtil/HMI.Simple.Util/ProductUtil.cs
@@ -28,13 +28,20 @@
             }
         }
 
+        /// <summary>
+        /// 鏍规嵁浜у搧鍨嬪彿鍐欓厤缃�
+        /// </summary>
+        /// <param name="model">浜у搧鍨嬪彿</param>
+        /// <param name="instance">TestStand涓婁笅鏂�</param>
+        /// <param name="errMsg">寮傚父淇℃伅</param>
+        /// <returns>鏄惁鎴愬姛</returns>
         public static bool WriteConfigToContextByModel(string model, object instance, out string errMsg)
         {
             errMsg = string.Empty;
             try
             {
                 string dir = RegUtil.GetLocaltion();
-                string path = Path.Combine(dir, "Config", "Product","Parameter", $"Parameter_{model}.data");
+                string path = Path.Combine(dir, "Config", "Product", "Parameter", $"Parameter_{model}.data");
                 return WriteConfigToContextByPath(path, instance, out errMsg);
             }
             catch (Exception ex)
@@ -44,6 +51,13 @@
             }
         }
 
+        /// <summary>
+        /// 鏍规嵁璺緞鍐欓厤缃�
+        /// </summary>
+        /// <param name="path">缁濆璺緞</param>
+        /// <param name="instance">TestStand涓婁笅鏂�</param>
+        /// <param name="errMsg">寮傚父淇℃伅</param>
+        /// <returns>鏄惁鎴愬姛</returns>
         public static bool WriteConfigToContextByPath(string path, object instance, out string errMsg)
         {
             errMsg = string.Empty;
@@ -51,7 +65,7 @@
             {
                 if (!File.Exists(path))
                 {
-                    throw new Exception("鏈壘鍒拌閰嶇疆锛岃妫�鏌�");
+                    throw new Exception($"鏈壘鍒拌閰嶇疆[{path}]锛岃妫�鏌�");
                 }
                 List<ParameterData> datas = XmlHelper.DeserializeFromXml<List<ParameterData>>(path);
                 foreach (var data in datas)

--
Gitblit v1.9.1