using HMI.Base; using HMI.Core.Entity; using HMI.Core.Manager; using HMI.Core.Setting; using HMI.Core.Util; using HMI.UI.Util; using HMI.Util; using LiveChartsCore; using LiveChartsCore.Drawing; using LiveChartsCore.Drawing.Layouts; using LiveChartsCore.Kernel.Sketches; using LiveChartsCore.SkiaSharpView; using LiveChartsCore.SkiaSharpView.Drawing; using LiveChartsCore.SkiaSharpView.Drawing.Geometries; using LiveChartsCore.SkiaSharpView.Drawing.Layouts; using LiveChartsCore.SkiaSharpView.Painting; using LiveChartsCore.SkiaSharpView.SKCharts; using LiveChartsCore.SkiaSharpView.VisualElements; using Microsoft.Web.WebView2.Core; using SkiaSharp; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Data; using System.IO; using System.Linq; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; namespace Plugin.DataBoard { public class CustomLegend : SKDefaultLegend { protected override Layout GetLayout(LiveChartsCore.Chart chart) { var stackLayout = new StackLayout { Orientation = ContainerOrientation.Horizontal, Padding = new Padding(0, 10, 0, 0), HorizontalAlignment = Align.Start, VerticalAlignment = Align.Middle, }; foreach (var series in chart.Series.Where(x => x.IsVisibleAtLegend)) { stackLayout.Children.Add(new LegendItem(series)); } return stackLayout; } } public class LegendItem : StackLayout { public LegendItem(ISeries series) { Orientation = ContainerOrientation.Horizontal; Padding = new Padding(0); VerticalAlignment = Align.Start; HorizontalAlignment = Align.Middle; Opacity = series.IsVisible ? 1 : 0.5f; var miniature = (IDrawnElement)series.GetMiniatureGeometry(null); Children = new List> { miniature, new LabelGeometry { Text = series.Name, TextSize = 12, Paint = new SolidColorPaint(SKColors.Black){ SKTypeface = SKFontManager.Default.MatchCharacter('汉') }, Padding = new Padding(5,0,10,0), VerticalAlign = Align.Middle, HorizontalAlign = Align.Start }}; } } /// /// UserControl1.xaml 的交互逻辑 /// public partial class DataBoard : PluginControl { public DataBoard() { DataContext = this; InitializeComponent(); //webview2.DefaultBackgroundColor = Color.Transparent;//Color.FromArgb(243, 249, 255); } private SolidColorPaint tooltipTextPaint = new SolidColorPaint(SKColors.Black) { SKTypeface = SKFontManager.Default.MatchCharacter('汉') }; public SolidColorPaint TooltipTextPaint { get => tooltipTextPaint; set { Set(ref tooltipTextPaint, value); } } #region chart0 public LabelVisual Chart0Title { get; set; } = new LabelVisual { Text = "投入产出统计", TextSize = 20, Paint = new SolidColorPaint(new SKColor(0, 0, 0)) { SKTypeface = SKFontManager.Default.MatchCharacter('汉') }, Padding = new LiveChartsCore.Drawing.Padding(15) }; private ISeries[] chart0_series = new ISeries[] { new ColumnSeries { Fill= new SolidColorPaint(new SKColor(34, 68, 139)), DataLabelsPaint = new SolidColorPaint(new SKColor(0, 0, 0)), DataLabelsPosition = LiveChartsCore.Measure.DataLabelsPosition.Top, Values = new int[]{ 0,0} } }; public ISeries[] Chart0_series { get => chart0_series; set { Set(ref chart0_series, value); } } private ObservableCollection chart0_yAxes = new ObservableCollection { new Axis { MinStep = 1, MinLimit = 0, LabelsPaint = new SolidColorPaint(new SKColor(0, 0, 0)), SeparatorsPaint = new SolidColorPaint { Color = SKColors.Black.WithAlpha(30), StrokeThickness = 0.5f }, TicksPaint = new SolidColorPaint { Color = SKColor.Empty, StrokeThickness = 0 }, } }; public ObservableCollection Chart0_yAxes { get => chart0_yAxes; set { Set(ref chart0_yAxes, value); } } private Axis[] chart0_xAxes = new Axis[] { new Axis { Labels = new string[]{"投入", "产出" }, LabelsPaint=new SolidColorPaint(new SKColor(0, 0, 0)) { SKTypeface = SKFontManager.Default.MatchCharacter('汉') }, LabelsRotation = 0, SeparatorsAtCenter = false, TicksPaint = new SolidColorPaint(new SKColor(35, 35, 35)), TicksAtCenter = true, ForceStepToMin = true, MinStep = 1 } }; public Axis[] Chart0_xAxes { get => chart0_xAxes; set { Set(ref chart0_xAxes, value); } } #endregion #region chart1 public LabelVisual Chart1Title { get; set; } = new LabelVisual { Text = "产品状态统计", TextSize = 20, Paint = new SolidColorPaint(new SKColor(0, 0, 0)) { SKTypeface = SKFontManager.Default.MatchCharacter('汉') }, Padding = new LiveChartsCore.Drawing.Padding(15) }; public ISeries[] Chart1_series { get; set; } = new PieSeries[] { new PieSeries { Name="Passed", Values = new int[]{ 0}, DataLabelsPosition = LiveChartsCore.Measure.PolarLabelsPosition.Outer, DataLabelsSize = 15, DataLabelsPaint = new SolidColorPaint(new SKColor(30, 30, 30)){ SKTypeface = SKFontManager.Default.MatchCharacter('汉') }, Fill = new SolidColorPaint(new SKColor(0, 128, 0)), DataLabelsFormatter = point =>point.StackedValue.Total>0? $"Passed\r\n计数:{point.Coordinate.PrimaryValue}\r\n占比:{point.StackedValue.Share:P2}":"", ToolTipLabelFormatter = point => $"{point.StackedValue.Share:P2}" }, new PieSeries { Values = new int[]{ 0} , Name="Failed", DataLabelsPosition = LiveChartsCore.Measure.PolarLabelsPosition.Outer, DataLabelsSize = 15, DataLabelsPaint = new SolidColorPaint(new SKColor(30, 30, 30)){ SKTypeface = SKFontManager.Default.MatchCharacter('汉') }, Fill = new SolidColorPaint(new SKColor(255, 0, 0)), DataLabelsFormatter = point =>point.StackedValue.Total>0? $"Failed\r\n计数:{point.Coordinate.PrimaryValue}\r\n占比:{point.StackedValue.Share:P2}":"", ToolTipLabelFormatter = point => $"{point.StackedValue.Share:P2}"}, }; #endregion #region chart2 public LabelVisual Chart2Title { get; set; } = new LabelVisual { Text = "良率统计", TextSize = 20, Paint = new SolidColorPaint(new SKColor(0, 0, 0)) { SKTypeface = SKFontManager.Default.MatchCharacter('汉') }, Padding = new LiveChartsCore.Drawing.Padding(15) }; public ISeries[] Chart2_series { get; set; } = new ISeries[] { new LineSeries { Name="直通率", Values = new double[]{ 0}, DataLabelsPosition = LiveChartsCore.Measure.DataLabelsPosition.Top, DataLabelsFormatter = point => $"直通率:{point.Coordinate.PrimaryValue:f2}%", DataLabelsSize = 15, DataLabelsPaint = new SolidColorPaint(new SKColor(30, 30, 30)){ SKTypeface = SKFontManager.Default.MatchCharacter('汉') }, Stroke = new SolidColorPaint(new SKColor(255,0,0)){ StrokeThickness = 2 }, Fill = null, GeometryStroke = new SolidColorPaint(new SKColor(255,0,0)){ StrokeThickness = 2 }, GeometrySize=5 }, new LineSeries { Name="良率", Values = new double[]{ 0}, DataLabelsPosition = LiveChartsCore.Measure.DataLabelsPosition.Bottom, DataLabelsFormatter = point => $"良率:{point.Coordinate.PrimaryValue:f2}%", DataLabelsSize = 10, DataLabelsPaint = new SolidColorPaint(new SKColor(30, 30, 30)){ SKTypeface = SKFontManager.Default.MatchCharacter('汉') }, Stroke = new SolidColorPaint(new SKColor(34, 68, 139)){ StrokeThickness = 2 }, GeometryStroke = new SolidColorPaint(new SKColor(34, 68, 139)){ StrokeThickness = 2 }, Fill = null, }, }; private ObservableCollection chart2_yAxes = new ObservableCollection { new Axis { LabelsPaint = new SolidColorPaint(new SKColor(0, 0, 0)), SeparatorsPaint = new SolidColorPaint { Color = SKColors.Black.WithAlpha(30), StrokeThickness = 0.5f }, TicksPaint = new SolidColorPaint { Color = SKColor.Empty, StrokeThickness = 0 }, MinLimit = 0 } }; public ObservableCollection Chart2_yAxes { get => chart2_yAxes; set { Set(ref chart2_yAxes, value); } } private ObservableCollection chart2_xAxes = new ObservableCollection { new Axis { Labels = new string[]{"" }, } }; public ObservableCollection Chart2_xAxes { get => chart2_xAxes; set { Set(ref chart2_xAxes, value); } } #endregion #region chart3 public LabelVisual Chart3Title { get; set; } = new LabelVisual { Text = "TOP10不良统计", TextSize = 20, Paint = new SolidColorPaint(new SKColor(0, 0, 0)) { SKTypeface = SKFontManager.Default.MatchCharacter('汉') }, Padding = new LiveChartsCore.Drawing.Padding(15) }; public ISeries[] Chart3_series { get; set; } = new ISeries[] { new RowSeries { Values = new SimpleData[]{}, DataLabelsPosition = LiveChartsCore.Measure.DataLabelsPosition.Left, DataLabelsFormatter = point => $"{point.Model.Name}", DataLabelsSize = 15, DataLabelsPadding = new Padding(30,0,0,0), DataLabelsTranslate = new LvcPoint(1, 0), // DataLabelsTranslate = new LvcPoint(-1, 0), DataLabelsPaint = new SolidColorPaint(new SKColor(255,0,0)){ SKTypeface = SKFontManager.Default.MatchCharacter('汉') }, YToolTipLabelFormatter = point => $"{point.Model.Name} {point.Model.Value}" }, }; public ObservableCollection chart3_yAxes = new ObservableCollection { new Axis { IsVisible = false } }; public ObservableCollection Chart3_yAxes { get => chart3_yAxes; set { Set(ref chart3_yAxes, value); } } private ObservableCollection chart3_xAxes = new ObservableCollection { new Axis { SeparatorsPaint = new SolidColorPaint(new SKColor(220, 220, 220)) } }; public ObservableCollection Chart3_xAxes { get => chart3_xAxes; set { Set(ref chart3_xAxes, value); } } #endregion 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; private string DataFolder; public override void InitFinish() { chart2.Legend = new CustomLegend(); iniFile = Path.Combine(BaseFolder, "Config.ini"); if (!File.Exists(iniFile)) { File.Create(iniFile); } DataFolder = ParamSetting.DataLogFolder; LoadProduct(); } private void PluginControl_Loaded(object sender, RoutedEventArgs e) { cb0.SelectedIndex = 0; cb1.SelectedIndex = 0; cb2.SelectedIndex = 0; cb3.SelectedIndex = 0; } 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 string[] GetDbFiles(DateTime startTime, DateTime endTime) { if (!Directory.Exists(DataFolder)) { return new string[0]; } string startName = $"Data_{startTime.ToString("yyyyMMdd")}"; string endName = $"Data_{endTime.ToString("yyyyMMdd")}"; var oldFiles = Directory.GetFiles(DataFolder, "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(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(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} Order BY id DESC;"; 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.EnsureCoreWebView2Async(); // 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(() => { Chart0_series[0].Values = new int[] { all, output }; //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(() => { Chart1_series[0].Values = new int[] { pieData["Passed"] }; Chart1_series[1].Values = new int[] { pieData["Failed"] }; // 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(() => { if (res.Count == 0) { res[DateTime.Now.ToString("yyyy-MM-dd")] = new PassRateData { onePassRate = 0, passRate = 0 }; } string[] keys = new string[res.Count]; double[] val0 = new double[res.Count]; double[] val1 = new double[res.Count]; int i = 0; foreach (var key in res.Keys) { keys[i] = key; val0[i] = res[key].onePassRate; val1[i] = res[key].passRate; i++; } Chart2_xAxes[0] = new Axis { Labels = keys, }; Chart2_series[0].Values = val0; Chart2_series[1].Values = val1; //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(() => { Chart3_series[0].Values = datasource.OrderBy(x => x.Value).ToList(); ; //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); } } } }