using HMI.Base; using HMI.Core.Entity; using HMI.Core.Manager; using HMI.Core.Util; using HMI.UI.Util; using HMI.Util; using Microsoft.Web.WebView2.Core; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; namespace Plugin.DataBoard { /// /// UserControl1.xaml 的交互逻辑 /// public partial class DataBoard : PluginControl { public DataBoard() { DataContext = this; InitializeComponent(); webview2.DefaultBackgroundColor = Color.Transparent;//Color.FromArgb(243, 249, 255); } private ObservableCollection _options = new ObservableCollection { new OptionData { Name = LangUtil.Get("bd.today"), Value = "today" }, //new OptionData { Name = LangUtil.Get("bd.today"), Value = "today" }, new OptionData { Name = LangUtil.Get("bd.week"), Value = "week" }, new OptionData { Name = LangUtil.Get("bd.month"), Value = "month" } }; public ObservableCollection Options { get { return _options; } set { Set(ref _options, value); } } private string iniFile; public override void InitFinish() { iniFile = Path.Combine(BaseFolder, "Config.ini"); if (!File.Exists(iniFile)) { File.Create(iniFile); } LoadProduct(); } private void PluginControl_Loaded(object sender, RoutedEventArgs e) { } private void LoadProduct() { List products = ProductManager.GetProducts>() ?? new List(); this.modelSelect.Items.Clear(); List productSource = new List(); foreach (var prd in products) { this.modelSelect.Items.Add(prd.Name); productSource.Add(prd.Name); } string model = IniFileHelper.ReadIniData("Config", "Model", "", iniFile); if (!string.IsNullOrEmpty(model)) { this.modelSelect.SelectedItem = model; } else if (products.Count > 0) { this.modelSelect.SelectedIndex = 0; } } private void RefreshAll() { try { var start0 = dtp00.SelectedDateTime ?? DateTime.Now; var end0 = dtp01.SelectedDateTime ?? DateTime.Now; RefreshChart0(start0, end0); } catch { } try { var start1 = dtp10.SelectedDateTime ?? DateTime.Now; var end1 = dtp11.SelectedDateTime ?? DateTime.Now; RefreshChart1(start1, end1); } catch { } try { var start2 = dtp20.SelectedDateTime ?? DateTime.Now; var end2 = dtp21.SelectedDateTime ?? DateTime.Now; RefreshChart2(start2, end2); } catch { } try { var start3 = dtp30.SelectedDateTime ?? DateTime.Now; var end3 = dtp31.SelectedDateTime ?? DateTime.Now; RefreshChart3(start3, end3); } catch { } } private void Button_Click(object sender, RoutedEventArgs e) { var btn = sender as Button; DateTime start, end; switch (btn.Name) { case "btnAll": RefreshAll(); break; case "btn0": start = dtp00.SelectedDateTime ?? DateTime.Now; end = dtp01.SelectedDateTime ?? DateTime.Now; RefreshChart0(start, end); break; case "btn1": start = dtp10.SelectedDateTime ?? DateTime.Now; end = dtp11.SelectedDateTime ?? DateTime.Now; RefreshChart1(start, end); break; case "btn2": start = dtp20.SelectedDateTime ?? DateTime.Now; end = dtp21.SelectedDateTime ?? DateTime.Now; RefreshChart2(start, end); break; case "btn3": start = dtp30.SelectedDateTime ?? DateTime.Now; end = dtp31.SelectedDateTime ?? DateTime.Now; RefreshChart3(start, end); break; default: break; } } 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 SelectSerialDataByTime(string model, DateTime start, DateTime end) { var s1 = DateTime.Now; string[] files = GetDbFiles(BaseFolder, start, end); if (files == null || files.Length <= 0) { return new List(); } string segment = string.Empty; if (!string.IsNullOrEmpty(model)) { segment = $"AND model = '{model}'"; } string sql = $@"SELECT * FROM serialData WHERE time BETWEEN '{start:yyyy-MM-dd HH:mm:ss}' AND '{end:yyyy-MM-dd HH:mm:ss}' {segment} ORDER BY time DESC;"; DataTable dt = new DataTable(); foreach (string file in files) { using (SqliteHelper helper = new SqliteHelper(file)) { dt.Merge(helper.GetDataTable(sql)); } } var s2 = DateTime.Now; log.Info($"SelectSerialDataByTime Cast: {(s2 - s1).TotalMilliseconds}"); var data = BeanUtil.ReadBeanFromDataTable(dt); log.Info($"Bean Cast: {(DateTime.Now - s2).TotalMilliseconds}"); return data; } private List SelectResultDataByTime(string model, DateTime start, DateTime end) { string[] files = GetDbFiles(BaseFolder, start, end); if (files == null || files.Length <= 0) { return new List(); } string segment = string.Empty; if (!string.IsNullOrEmpty(model)) { segment = $"AND model = '{model}'"; } string sql = $@"SELECT * FROM testResult WHERE time BETWEEN '{start:yyyy-MM-dd HH:mm:ss}' AND '{end:yyyy-MM-dd HH:mm:ss}' {segment};"; DataTable dt = new DataTable(); foreach (string file in files) { using (SqliteHelper helper = new SqliteHelper(file)) { var temp = helper.GetDataTable(sql); dt.Merge(temp); } } return BeanUtil.ReadBeanFromDataTable(dt); } private void webview2_Loaded(object sender, RoutedEventArgs e) { string path = Path.Combine(PathHelper.AppFolder, "Libs", "Static", "test.html"); webview2.Source = new Uri(path); } private void Webview2_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e) { cb0.SelectedIndex = 0; cb1.SelectedIndex = 0; cb2.SelectedIndex = 0; cb3.SelectedIndex = 0; } private void webview2_SizeChanged(object sender, SizeChangedEventArgs e) { var width = this.webview2.ActualWidth - 100; var height = this.webview2.ActualHeight; 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 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 snCache = new HashSet(); // 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) { dtp00.SelectedDateTime = start; dtp01.SelectedDateTime = end; string model = modelSelect.SelectedItem?.ToString(); Task.Run(() => { try { Dispatcher.BeginInvoke(new Action(() => { webview2.CoreWebView2?.ExecuteScriptAsync($"loading0('加载中,请稍后...')"); })); List datas = SelectResultDataByTime(model, start, end); datas.OrderByDescending(e => e.time); int all = 0, output = 0; HashSet snCache = new HashSet(); 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}])"); })); } catch (Exception ex) { log.Error("RefreshChart0 Error.", ex); ToastHelper.Error("表1刷新失败!"); } }); } private void RefreshChart1(DateTime start, DateTime end) { dtp10.SelectedDateTime = start; dtp11.SelectedDateTime = end; string model = modelSelect.SelectedItem?.ToString(); Task.Run(() => { try { Dispatcher.BeginInvoke(new Action(() => { webview2.CoreWebView2?.ExecuteScriptAsync($"loading1('加载中,请稍后...')"); })); List datas = SelectResultDataByTime(model, start, end); datas = datas.OrderByDescending(e => e.time).ToList(); Dictionary pieData = new Dictionary { { "Passed",0}, { "Failed",0}, //{ "Action",0}, //{ "Wait",0}, }; //if (datas == null || datas.Count <= 0) //{ // pieData = new Dictionary { // { "Passed",null}, // { "Failed",null}, //}; //} HashSet snCache = new HashSet(); foreach (var data in datas) { 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})"); })); } catch (Exception ex) { log.Error("RefreshChart1 Error.", ex); ToastHelper.Error("表2刷新失败!"); } }); } //private void RefreshChart2(DateTime start, DateTime end) //{ // dtp20.SelectedDateTime = start; // dtp21.SelectedDateTime = end; // List datas = SelectSerialDataByTime(start, end); // var groups = // datas.Where(e => e.status == "Passed" || e.status == "Failed").GroupBy(d => d.time.ToString("yyyy-MM-dd")); // Dictionary res = new Dictionary(); // foreach (var group in groups) // { // Dictionary snStatusCache = new Dictionary(); // double all = 0, oneTimePass = 0, passed = 0; // var groupDatas = group.ToList(); // groupDatas = groupDatas.OrderBy(e => e.time).ToList(); // foreach (var data in groupDatas) // { // if (snStatusCache.ContainsKey(data.sn)) // { // if (snStatusCache[data.sn] != "Passed" && data.status == "Passed") // { // passed++; // } // else if (snStatusCache[data.sn] == "Passed" && data.status == "Passed") // { // if (oneTimePass > 0) oneTimePass--; // } // } // else // { // all++; // if (data.status == "Passed") // { // passed++; // oneTimePass++; // } // snStatusCache.Add(data.sn, data.status); // } // } // res.Add(group.Key, new PassRateData // { // time = group.Key, // onePassRate = oneTimePass / all * 100, // passRate = passed / all * 100, // }); // } // string fields = "[", vals0 = "[", vals1 = "["; // foreach (var key in res.Keys) // { // fields += $"'{key}',"; // vals0 += $"{res[key].onePassRate},"; // vals1 += $"{res[key].passRate},"; // } // fields += "]"; // vals0 += "]"; // vals1 += "]"; // var names = $"['{this.lang("bd.onePassRate")}','{this.lang("bd.passRate")}']"; // webview2.CoreWebView2?.ExecuteScriptAsync($"drawChart2({fields},{names},{vals0},{vals1})"); //} private void RefreshChart2(DateTime start, DateTime end) { dtp20.SelectedDateTime = start; dtp21.SelectedDateTime = end; string model = modelSelect.SelectedItem?.ToString(); Task.Run(() => { try { Dispatcher.BeginInvoke(new Action(() => { webview2.CoreWebView2?.ExecuteScriptAsync($"loading2('加载中,请稍后...')"); })); List datas = SelectResultDataByTime(model, start, end); var groups = datas.GroupBy(d => d.time.ToString("yyyy-MM-dd")); Dictionary res = new Dictionary(); foreach (var group in groups) { Dictionary snStatusCache = new Dictionary(); double all = 0, oneTimePass = 0, passed = 0; var groupDatas = group.ToList(); groupDatas = groupDatas.OrderByDescending(e => e.time).ToList(); foreach (var data in groupDatas) { if (!snStatusCache.ContainsKey(data.sn)) { 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"; } } } res.Add(group.Key, new PassRateData { time = group.Key, onePassRate = oneTimePass / all * 100, passRate = passed / all * 100, }); } string fields = "[", vals0 = "[", vals1 = "["; foreach (var key in res.Keys) { 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})"); })); } catch (Exception ex) { log.Error("RefreshChart2 Error.", ex); ToastHelper.Error("表3刷新失败!"); } }); } private void RefreshChart3(DateTime start, DateTime end) { dtp30.SelectedDateTime = start; dtp31.SelectedDateTime = end; string model = modelSelect.SelectedItem?.ToString(); Task.Run(() => { try { Dispatcher.BeginInvoke(new Action(() => { webview2.CoreWebView2?.ExecuteScriptAsync($"loading3('加载中,请稍后...')"); })); var st = DateTime.Now; List datas = SelectSerialDataByTime(model, start, end); var s2 = DateTime.Now; log.Info($"RefreshChart3 Data Cast {(s2 - st).TotalMilliseconds}"); Dictionary pieData = new Dictionary(); List datasource = new List(); //HashSet snCache = new HashSet(); foreach (var data in datas) { //if (snCache.Contains(data.sn)) continue; if (data.status != "Failed") continue; if (pieData.ContainsKey(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(); } 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},"; } Dispatcher.BeginInvoke(new Action(() => { webview2.CoreWebView2?.ExecuteScriptAsync($"drawChart3([{names}],[{vals}])"); })); } catch (Exception ex) { log.Error("RefreshChart3 Error.", ex); ToastHelper.Error("表4刷新失败!"); } }); } private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { ComboBox cb = sender as ComboBox; string val = (e.AddedItems[0] as OptionData)?.Value?.ToString(); DateTime start, end; if (val == "today") { DateUtil.GetDayTime(out start, out end); } else if (val == "week") { DateUtil.GetWeekTime(out start, out end); } else { DateUtil.GetMonthTime(out start, out end); } switch (cb.Name) { case "cb0": RefreshChart0(start, end); break; case "cb1": RefreshChart1(start, end); break; case "cb2": RefreshChart2(start, end); break; case "cb3": RefreshChart3(start, end); break; default: break; } } private void modelSelect_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (e.AddedItems.Count > 0) { IniFileHelper.WriteIniData("Config", "Model", e.AddedItems[0].ToString(), iniFile); } } } }