ソースを参照

Update CSV Writer

Zixuan 2 週間 前
コミット
3aba14e10d

+ 1 - 0
Analizer/ProximaAnalizer/Data/DB.cs

@@ -65,4 +65,5 @@ public class EventData
     public string? Description { get; set; }
     public DateTime Occur_Time { get; set; }
     public string? Source { get; set; }
+    public string? Event_Enum { get; set; }
 }

+ 2 - 1
Analizer/ProximaAnalizer/Helpers/DisplayDataHelper.cs

@@ -2,7 +2,7 @@
 
 internal class DisplayDataHelper(IDictionary<string, object> Left, IDictionary<string, object> Right)
 {
-    public HashSet<DateTime> Time { get; } = [];
+    public List<DateTime> Time { get; } = [];
     public Dictionary<string, List<float>> DataLeft { get; } = [];
     public Dictionary<string, List<float>> DataRight { get; } = [];
 
@@ -23,6 +23,7 @@ internal class DisplayDataHelper(IDictionary<string, object> Left, IDictionary<s
 
         this.ClearData();
 
+
         foreach (var item in main)
         {
             if (item is not IDictionary<string, object> data)

+ 9 - 8
Analizer/ProximaAnalizer/ViewModels/DBInfoTraceViewModel.cs

@@ -58,7 +58,7 @@ internal partial class DBInfoTraceViewModel : ObservableObject
 
         if (!this._DBDataHelper.GetRecipeSteps(_traceData.ProcessData.Guid, out string reason, out List<RecipeStepData>? recipeSteps) || recipeSteps is null)
         {
-            MessageBox.Show(reason, "Warning", MessageBoxButton.OK, MessageBoxImage.Error);
+            MessageBox.Show(reason, "Warning", MessageBoxButton.OK, MessageBoxImage.Warning);
             return;
         }
 
@@ -66,7 +66,7 @@ internal partial class DBInfoTraceViewModel : ObservableObject
 
         if (!this._DBDataHelper.GetFirstData(_traceData.ProcessData.Process_Begin_Time, out string error, out Dictionary<string, object>? firstData) || firstData is null)
         {
-            MessageBox.Show(error, "Warning", MessageBoxButton.OK, MessageBoxImage.Error);
+            MessageBox.Show(error, "Warning", MessageBoxButton.OK, MessageBoxImage.Warning);
             return;
         }
 
@@ -233,13 +233,13 @@ internal partial class DBInfoTraceViewModel : ObservableObject
     {
         if (!this.RecipeSteps.Any(t => t.Value.IsSelected))
         {
-            MessageBox.Show("Recipe Step 未选择", "Warning", MessageBoxButton.OK, MessageBoxImage.Error);
+            MessageBox.Show("Recipe Step 未选择", "Warning", MessageBoxButton.OK, MessageBoxImage.Warning);
             return;
         }
 
         if (this.Left.Count == 0 && Right.Count == 0)
         {
-            MessageBox.Show("分析数据 未选择", "Warning", MessageBoxButton.OK, MessageBoxImage.Error);
+            MessageBox.Show("分析数据 未选择", "Warning", MessageBoxButton.OK, MessageBoxImage.Warning);
             return;
         }
 
@@ -274,7 +274,7 @@ internal partial class DBInfoTraceViewModel : ObservableObject
         this.PlotControl.Refresh();
     }
 
-    public void GenerateAlarm(List<EventData> alarm)
+    private void GenerateAlarm(List<EventData> alarm)
     {
         this.Alarms.Clear();
         this.Alarms.AddRange(alarm);
@@ -283,13 +283,13 @@ internal partial class DBInfoTraceViewModel : ObservableObject
         HashSet<DateTime> dup = [];
         foreach (EventData item in alarm)
         {
-            if (string.IsNullOrEmpty(item.Description))
+            if (string.IsNullOrEmpty(item.Event_Enum))
                 continue;
 
-            if (intervalFilter.TryGetValue(item.Description, out DateTime time) &&
+            if (intervalFilter.TryGetValue(item.Event_Enum, out DateTime time) &&
                 (item.Occur_Time - time).TotalSeconds < AlarmInverval)
                 continue;
-            intervalFilter[item.Description] = item.Occur_Time;
+            intervalFilter[item.Event_Enum] = item.Occur_Time;
 
 
             switch (item.Level)
@@ -351,6 +351,7 @@ internal partial class DBInfoTraceViewModel : ObservableObject
         IDialogParameters para = new DialogParameters
         {
             { "Data", this._DisplayDataHelper},
+            {"Alarm", this.Alarms }
         };
         this._dialogService.Show("TraceData", para, null);
     }

+ 157 - 1
Analizer/ProximaAnalizer/ViewModels/Dialog/TraceDataListViewModel.cs

@@ -1,9 +1,30 @@
-namespace ProximaAnalizer.ViewModels.Dialog;
+using Dm.util;
+using Microsoft.Win32;
+using ProximaAnalizer.Helpers;
+using ScottPlot;
+using SqlSugar;
+using System.Collections.ObjectModel;
+using System.IO;
+using System.Reflection.Metadata.Ecma335;
+using System.Security.Claims;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls.Ribbon;
+
+namespace ProximaAnalizer.ViewModels.Dialog;
 
 internal partial class TraceDataListViewModel : ObservableObject, IDialogAware
 {
     public DialogCloseListener RequestClose { get; set; }
 
+    public string Header { get; set; } = "DataLog";
+
+    [ObservableProperty]
+    private ObservableDictionary<DateTime, DynamicDisplay> _DynamicDisplay = [];
+
+    [ObservableProperty]
+    private ObservableCollection<string> _Headers = [];
+
     public bool CanCloseDialog()
     {
 
@@ -16,5 +37,140 @@ internal partial class TraceDataListViewModel : ObservableObject, IDialogAware
 
     public void OnDialogOpened(IDialogParameters parameters)
     {
+        if (!parameters.TryGetValue("Data", out object? trace))
+            return;
+
+        if (trace is not DisplayDataHelper traceData)
+            return;
+
+        Dictionary<string, List<float>> cache = [];
+        cache = cache.Concat(traceData.DataLeft).ToDictionary();
+        if (traceData.DataRight is not null)
+            cache = cache.Concat(traceData.DataRight).ToDictionary();
+        this.Headers.Clear();
+        HashSet<string> headers = new();
+        for (int i = 0; i < traceData.Time.Count; i++)
+        {
+            DynamicDisplay dynamicDisplay = new();
+            long ticks = traceData.Time[i].Ticks;
+            ticks -= ticks % 10000000;
+            dynamicDisplay.Time = new(ticks);
+            this.DynamicDisplay[dynamicDisplay.Time] = dynamicDisplay;
+
+            foreach (var item in cache)
+            {
+                PairData pairData = new()
+                {
+                    Name = item.Key,
+                    Value = item.Value[i].ToString("0.00"),
+                };
+                headers.Add(item.Key);
+                dynamicDisplay.Data.Add(pairData);
+            }
+        }
+
+        Headers.AddRange(headers);
+
+        if (!parameters.TryGetValue("Alarm", out object? rawAlarm))
+            return;
+
+        if (rawAlarm is not IEnumerable<EventData> alarms)
+            return;
+
+        foreach (EventData eventData in alarms)
+        {
+            if (string.IsNullOrEmpty(eventData.Description))
+                continue;
+
+            long ticks = eventData.Occur_Time.Ticks;
+            ticks -= ticks % 10000000;
+
+            if (!this.DynamicDisplay.TryGetValue(new(ticks), out DynamicDisplay? display) || display is null)
+                continue;
+
+            display.Alarm.Add(eventData.Description);
+        }
+    }
+
+    [RelayCommand]
+    private void Export()
+    {
+        SaveFileDialog saveFileDialog = new()
+        {
+            Filter = "History files |*.csv;",
+            FileName = "DataLog.csv",
+            InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
+        };
+
+        if (saveFileDialog.ShowDialog() != true)
+            return;
+
+        try
+        {
+            using StreamWriter sw = new(saveFileDialog.FileName);
+            StringBuilder header = new();
+            header.append("Time");
+            header.Append(',');
+            foreach (var item in Headers)
+            {
+                header.append(item);
+                header.Append(',');
+            }
+
+            header.append("Alarm");
+            sw.WriteLine(header);
+
+            foreach (var item in this.DynamicDisplay)
+            {
+                StringBuilder sb = new();
+                sb.Append(item.Value.Time.ToString("yyyy-MM-dd HH:mm:ss.f"));
+                sb.Append(',');
+                foreach (var data in item.Value.Data)
+                {
+                    sb.append(data.Value);
+                    sb.Append(',');
+                }
+                StringBuilder sbAlarm = new();
+
+                for (int i = 0; i < item.Value.Alarm.Count; i++)
+                {
+                    sbAlarm.Append($"{item.Value.Alarm[i].Replace("°C", string.Empty)}");
+                    if (i != item.Value.Alarm.Count - 1)
+                        sbAlarm.Append(Environment.NewLine);
+                }
+
+                if (item.Value.Alarm.Count != 0)
+                    sb.append($"\"{sbAlarm}\"");
+
+                sw.WriteLine(sb);
+            }
+            MessageBoxResult result = MessageBox.Show("文件保存成功,是否查看文件?", "Save History File", MessageBoxButton.YesNo, MessageBoxImage.Question);
+            FileInfo fileInfo = new(saveFileDialog.FileName);
+            if (result == MessageBoxResult.Yes && fileInfo.Directory is not null)
+                System.Diagnostics.Process.Start("Explorer.exe", fileInfo.Directory.FullName);
+
+        }
+        catch
+        {
+            MessageBox.Show("文件保存失败!", "Save History File", MessageBoxButton.OK, MessageBoxImage.Error);
+        }
+
     }
 }
+
+public class DynamicDisplay
+{
+    public DateTime Time { get; set; }
+
+
+    public List<PairData> Data { get; } = [];
+
+
+    public List<string> Alarm { get; } = [];
+}
+
+public class PairData
+{
+    public string? Name { get; set; }
+    public string? Value { get; set; }
+}

+ 4 - 1
Analizer/ProximaAnalizer/Views/DBInfoTrace.xaml

@@ -198,12 +198,15 @@
                                             <ColumnDefinition Width="8"/>
                                             <ColumnDefinition Width="48"/>
                                             <ColumnDefinition Width="8"/>
+                                            <ColumnDefinition Width="180"/>
+                                            <ColumnDefinition Width="32"/>
                                             <ColumnDefinition Width="auto"/>
                                         </Grid.ColumnDefinitions>
                                         <TextBlock VerticalAlignment="Center" HorizontalAlignment="Left"  Text="{Binding Occur_Time, StringFormat=HH:mm:ss.fff}"/>
                                         <TextBlock Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Center" Text="{Binding Source}" ToolTip="{Binding Source}"/>
                                         <TextBlock Grid.Column="4" VerticalAlignment="Center" HorizontalAlignment="Center" Text="{Binding Level}" ToolTip="{Binding Level}"/>
-                                        <TextBlock Grid.Column="6" VerticalAlignment="Center" HorizontalAlignment="Left" Text="{Binding Description}" ToolTip="{Binding Description}"/>
+                                        <TextBlock Grid.Column="6" VerticalAlignment="Center" HorizontalAlignment="Left" Text="{Binding Event_Enum}" ToolTip="{Binding Event_Enum}"/>
+                                        <TextBlock Grid.Column="8" VerticalAlignment="Center" HorizontalAlignment="Left" Text="{Binding Description}" ToolTip="{Binding Description}"/>
                                     </Grid>
                                 </DataTemplate>
                             </ItemsControl.ItemTemplate>

+ 86 - 2
Analizer/ProximaAnalizer/Views/Dialog/TraceDataList.xaml

@@ -6,7 +6,91 @@
              xmlns:local="clr-namespace:ProximaAnalizer.Views.Dialog"
              mc:Ignorable="d" 
              d:DesignHeight="450" d:DesignWidth="800">
-    <Grid>
-            
+    <UserControl.Resources>
+        <ResourceDictionary Source="/UICommon;component/Resources.xaml"/>
+    </UserControl.Resources>
+    <Grid Margin="4">
+        <Grid.RowDefinitions>
+            <RowDefinition Height="auto"/>
+            <RowDefinition Height="auto"/>
+            <RowDefinition/>
+            <RowDefinition Height="4"/>
+            <RowDefinition Height="auto"/>
+        </Grid.RowDefinitions>
+            <DataGrid Grid.Row="2" ItemsSource="{Binding DynamicDisplay}" 
+                    CanUserAddRows="False"
+                    CanUserDeleteRows="False"
+                    CanUserSortColumns="False"
+                    AutoGenerateColumns="False"
+                  HorizontalScrollBarVisibility="Auto"
+                  VerticalAlignment="Center"
+                  HorizontalAlignment="Center"
+                    TextElement.FontSize="14">
+            <DataGrid.Columns>
+                <DataGridTemplateColumn Header="Time">
+                    <DataGridTemplateColumn.CellTemplate>
+                        <DataTemplate>
+                            <TextBlock Margin="8,4" Text="{Binding Value.Time, StringFormat=yyyy-MM-dd HH:mm:ss}"></TextBlock>
+                        </DataTemplate>
+                    </DataGridTemplateColumn.CellTemplate>
+                </DataGridTemplateColumn>
+                <DataGridTemplateColumn>
+                    <DataGridTemplateColumn.Header>
+                        <ItemsControl ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:TraceDataList}, Path=DataContext.Headers}">
+                            <ItemsControl.ItemTemplate>
+                                <DataTemplate>
+                                    <TextBlock Text="{Binding}" Width="200" HorizontalAlignment="Center" ToolTip="{Binding}"/>
+                                </DataTemplate>
+                            </ItemsControl.ItemTemplate>
+                            <ItemsControl.ItemsPanel>
+                                <ItemsPanelTemplate>
+                                    <StackPanel Orientation="Horizontal"></StackPanel>
+                                </ItemsPanelTemplate>
+                            </ItemsControl.ItemsPanel>
+                        </ItemsControl>
+                    </DataGridTemplateColumn.Header>
+                    <DataGridTemplateColumn.CellTemplate>
+                        <DataTemplate>
+                            <ItemsControl ItemsSource="{Binding Value.Data}">
+                                <ItemsControl.ItemTemplate>
+                                    <DataTemplate>
+                                        <Grid Width="200">
+                                            <TextBlock Text="{Binding Value}"  HorizontalAlignment="Center"/>
+                                        </Grid>
+                                    </DataTemplate>
+                                </ItemsControl.ItemTemplate>
+                                <ItemsControl.ItemsPanel>
+                                    <ItemsPanelTemplate>
+                                        <StackPanel Orientation="Horizontal"></StackPanel>
+                                    </ItemsPanelTemplate>
+                                </ItemsControl.ItemsPanel>
+                            </ItemsControl>
+                        </DataTemplate>
+                    </DataGridTemplateColumn.CellTemplate>
+                </DataGridTemplateColumn>
+
+                <DataGridTemplateColumn Header="Alarm" Width="*">
+                    <DataGridTemplateColumn.CellTemplate>
+                        <DataTemplate>
+                            <ItemsControl ItemsSource="{Binding Value.Alarm}">
+                                <ItemsControl.ItemTemplate>
+                                    <DataTemplate>
+                                        <Grid>
+                                            <TextBlock Text="{Binding}" HorizontalAlignment="Left"></TextBlock>
+                                        </Grid>
+                                    </DataTemplate>
+                                </ItemsControl.ItemTemplate>
+                                <ItemsControl.ItemsPanel>
+                                    <ItemsPanelTemplate>
+                                        <StackPanel Orientation="Vertical"></StackPanel>
+                                    </ItemsPanelTemplate>
+                                </ItemsControl.ItemsPanel>
+                            </ItemsControl>
+                        </DataTemplate>
+                    </DataGridTemplateColumn.CellTemplate>
+                </DataGridTemplateColumn>
+            </DataGrid.Columns>
+        </DataGrid>
+        <Button Grid.Row="4" Style="{StaticResource FunctionButton}" Command="{Binding ExportCommand}">导出csv</Button>
     </Grid>
 </UserControl>