using Mapster; using OpenTK.Graphics.ES20; using ProximaAnalizer.Helpers; using ScottPlot; using ScottPlot.Plottables; using ScottPlot.WPF; using SqlSugar; using System.Windows; using System.Windows.Media; using Universal; namespace ProximaAnalizer.ViewModels; internal partial class DBInfoTraceViewModel : ObservableObject { public DBInfoTraceViewModel(TraceData traceData, SqlSugarCustom sqlSugarCustom, IEventAggregator eventAggregator, IDialogService dialogService) { this.traceData = traceData; this.sqlSugarCustom = sqlSugarCustom; this.dialogService = dialogService; this.Left = []; this.Right = []; this.PlotControl = new(); this._DBDisplayHelper = new(Left, Right); this._PlotHelper = new(this.PlotControl); this._PlotHelper.InitPlot(); eventAggregator.GetEvent().Subscribe(Search); } private readonly TraceData traceData; private readonly SqlSugarCustom sqlSugarCustom; private readonly IDialogService dialogService; private readonly PlotHepler _PlotHelper; private readonly DBDisplayHelper _DBDisplayHelper; [ObservableProperty] private WpfPlot _PlotControl; [ObservableProperty] private ObservableDictionary _RecipeSteps = []; [ObservableProperty] private IDictionary? _Hierachy; [ObservableProperty] private ObservableDictionary _Left = []; [ObservableProperty] private ObservableDictionary _Right = []; private readonly Stack> Cache = new(); [ObservableProperty] private bool _DisplayAlarm = false; private bool AutoGenerated = false; [RelayCommand] private void Selected(SelectRecipeStep step) { if (RecipeSteps is null) return; if (sqlSugarCustom.Client is null) return; if (AutoGenerated) { UnSelected(step); return; } if (RecipeSteps.Where(t => t.Value.IsSelected).Count() != 2) return; DateTime start = RecipeSteps.Where(t => t.Value.IsSelected).First().Key; DateTime end = RecipeSteps.Where(t => t.Value.IsSelected).Last().Key; RecipeSteps.Where(t => t.Key >= start && t.Key <= end).Foreach(t => t.Value.IsSelected = true); this.AutoGenerated = true; } [RelayCommand] private void UnSelected(SelectRecipeStep step) { RecipeSteps.Where(t => t.Value.IsSelected).Foreach(t => t.Value.IsSelected = false); this.AutoGenerated = false; } [RelayCommand] private void SelectHierachy(KeyValuePair item) { if (this.Hierachy is null) return; if (item.Value is IDictionary next) { this.Cache.Push(this.Hierachy); this.Hierachy = next; return; } //this.Left.TryAdd((string)item.Value, item.Value); //IDialogParameters parameters, Action< IDialogResult > callback IDialogParameters para = new DialogParameters() { { "Line", item.Value } }; dialogService.Show("LinePicker", para, AddLineCallback); } [RelayCommand] private void EditLine(KeyValuePair item) { IDialogParameters para = new DialogParameters() { { "Line", item.Key } }; dialogService.Show("LinePicker", para, AddLineCallback); } private void AddLineCallback(IDialogResult dialogResult) { dialogResult.Parameters.TryGetValue("Line", out LineType? lineType); dialogResult.Parameters.TryGetValue("Name", out string? line); dialogResult.Parameters.TryGetValue("Axis", out string? Axis); if (lineType is null || string.IsNullOrEmpty(line) || string.IsNullOrEmpty(Axis)) return; ObservableDictionary? lineCollection = Axis switch { "L" => Left, "R" => Right, _ => default }; if (lineCollection is null) return; if (lineCollection.TryGetValue(line, out object? oldType) && oldType is LineType oldLine) oldLine.IsEnable = true; lineCollection[line] = lineType; } [RelayCommand] private void Return() { if (this.Cache.TryPop(out var output) && output is not null) this.Hierachy = output; } [RelayCommand] private void Search() { if (traceData.ProcessData is null) return; if (sqlSugarCustom.Client is null) return; this.Cache.Clear(); this.RecipeSteps ??= []; this.RecipeSteps.Clear(); this.Clear(string.Empty); DateTime beginTime = traceData.ProcessData.Process_Begin_Time; DateTime endTime = traceData.ProcessData.Process_End_Time; long beginTicks = beginTime.Ticks; long endTicks = endTime.Ticks; List recipeSteps; try { recipeSteps = sqlSugarCustom.Client.Queryable().AS("recipe_step_data") .Where(t => t.Process_Data_Guid == traceData.ProcessData.Guid) .OrderBy(t => t.Step_Begin_Time).ToList(); } catch { MessageBox.Show($"recipe_step_data 记录不存在", "Warning", MessageBoxButton.OK, MessageBoxImage.Error); return; } if (recipeSteps.Count == 0) { MessageBox.Show($"recipe_step 步骤数量为0", "Warning", MessageBoxButton.OK, MessageBoxImage.Error); return; } foreach (var item in recipeSteps) { SelectRecipeStep step = new(); item.Adapt(step); this.RecipeSteps.TryAdd(item.Step_Begin_Time, step); } dynamic pm; dynamic system; try { pm = sqlSugarCustom.Client.Queryable().AS($"\"{beginTime:yyyyMMdd}.PM1\"").First(); system = sqlSugarCustom.Client.Queryable().AS($"\"{beginTime:yyyyMMdd}.System\"").First(); } catch { MessageBox.Show($"{beginTime:yyyyMMdd} 记录不存在", "Warning", MessageBoxButton.OK, MessageBoxImage.Error); return; } GeneralProcessData processData = new(); if (pm is not IDictionary input) return; if (!processData.ToDictionary(input, out Dictionary? output) || output is null) return; if (output["PM1"] is not IDictionary pmData) return; if (!processData.ToDictionary(system, out Dictionary? systemDic) || systemDic is null) return; Dictionary temp = []; Dictionary PM1 = []; Dictionary System = []; temp.Add("PM1", PM1); temp.Add("System", System); processData.CreateTablePM(pmData, PM1); processData.CreateTableSystem(systemDic!, System); this.Hierachy = temp; this.Cache.Push(temp); } [RelayCommand] private void RemoveLeft(string key) { this.Left.TryRemove(key, out object? line); if (line is LineType lineType) lineType.IsEnable = true; } [RelayCommand] private void RemoveRight(string key) { this.Right.TryRemove(key, out object? line); if (line is LineType lineType) lineType.IsEnable = true; } [RelayCommand] private void Clear(string para) { switch (para) { case "L": this.Left.Foreach(t => ((LineType)t.Value).IsEnable = true); this.Left.Clear(); break; case "R": this.Right.Foreach(t => ((LineType)t.Value).IsEnable = true); this.Right.Clear(); break; default: this.Right.Foreach(t => ((LineType)t.Value).IsEnable = true); this.Right.Clear(); this.Left.Foreach(t => ((LineType)t.Value).IsEnable = true); this.Left.Clear(); break; } } [RelayCommand] private void GeneratePlot() { if (this.sqlSugarCustom.Client is null) return; if (!this.RecipeSteps.Any(t => t.Value.IsSelected)) return; DateTime startTime = this.RecipeSteps.Where(t => t.Value.IsSelected).First().Key; DateTime endTime = this.RecipeSteps.Where(t => t.Value.IsSelected).Last().Key; ObjectFuncModel whereFunc = ObjectFuncModel.Create("Format", "time", ">", "{long}:" + $"{startTime.Ticks}", "&&", "time", "<", "{long}:" + $"{endTime.Ticks}"); List pm1 = sqlSugarCustom.Client.Queryable().AS($"\"{startTime:yyyyMMdd}.PM1\"").Where(whereFunc).ToList(); List system = sqlSugarCustom.Client.Queryable().AS($"\"{startTime:yyyyMMdd}.System\"").Where(whereFunc).ToList(); this._DBDisplayHelper.ClearData(); this._DBDisplayHelper.CreateData(pm1, system); this.PlotControl.Plot.Clear(); foreach (var item in this._DBDisplayHelper.DataLeft) this._PlotHelper.AddLeftLine(this._DBDisplayHelper.Time, item.Value, ((LineType)Left[item.Key])!.LinePattern, MarkerStyle.None, 1.5f, ((LineType)Left[item.Key])!.HexRGB); foreach (var item in this._DBDisplayHelper.DataRight) this._PlotHelper.AddRightLine(this._DBDisplayHelper.Time, item.Value, ((LineType)Right[item.Key])!.LinePattern, MarkerStyle.None, 1.5f, ((LineType)Right[item.Key])!.HexRGB); if (this.DisplayAlarm) this.CreateAlarm(startTime, endTime); this.PlotControl.Plot.Axes.AutoScale(); this.PlotControl.Refresh(); } private void CreateAlarm(DateTime start, DateTime end) { if (this.sqlSugarCustom is null || sqlSugarCustom.Client is null) return; List alarm = sqlSugarCustom.Client.Queryable().AS($"event_data").Where(t => t.Occur_Time >= start && t.Occur_Time <= end && (t.Level == "Alarm" || t.Level == "Warning")).ToList(); if (alarm is null) return; alarm.Foreach(item => _ = item.Level switch { "Alarm" => this._PlotHelper.AddAlarmLine(item.Occur_Time, $"{item.Source}"), "Warning" => this._PlotHelper.AddWarningLine(item.Occur_Time, $"{item.Source}"), _ => true }); } [RelayCommand] private void ViewTraceData() { IDialogParameters para = new DialogParameters { { "Data", this._DBDisplayHelper}, }; this.dialogService.Show("TraceData", para, null); } [RelayCommand] private void ReScale(string para) { switch (para) { case "+": this.PlotControl.Plot.Axes.Zoom(1.25, 1); break; case "-": this.PlotControl.Plot.Axes.Zoom(0.8, 1); break; case "add": this.PlotControl.Plot.Axes.Zoom(1, 1.25); break; case "minus": this.PlotControl.Plot.Axes.Zoom(1, 0.8); break; default: this.PlotControl.Plot.Axes.AutoScale(); this.PlotControl.Plot.Axes.Zoom(1.085, 1); break; } this.PlotControl.Refresh(); } } public partial class SelectRecipeStep : ObservableObject { [ObservableProperty] private bool _IsSelected; public string? Guid { get; set; } public DateTime Step_Begin_Time { get; set; } public DateTime Step_End_Time { get; set; } public string? Step_Name { get; set; } public float Step_Time { get; set; } public int Step_Number { get; set; } public string? Sub_Recipe_Step_Time { get; set; } public string? Sub_Recipe_Step_Number { get; set; } public string? Sub_Recipe_Step_Name { get; set; } public string? Sub_Recipe_Loop_Info { get; set; } public string? Temp_correction { get; set; } public string? Temp_pid { get; set; } }