feat: massive rework

1) GSS2.Core:
- strip prefixes in GSS2.Core.Analysis.AmineContent namespace class names
- add IEnumerable<double>.Variance extension
- remake analysis + update database so not needed to store all every file, calibration data also stored in database, also currently capturing images stored in system temporary directory and rewriting every time
2) GSS.UI.Core: AsyncImageRecordViewModel make zoom and pans public
3) GSS:
- remove image-storage-clear command
- remove ResultsView and ResultsViewModel, results presented in analysis
- rework calibration views
- add analysis views
- add text and number fields editors view
- add confirmation view on danger buttons
This commit is contained in:
2026-05-13 12:56:32 +03:00
parent ec95eef375
commit 3cc4d21947
63 changed files with 4359 additions and 3961 deletions
@@ -7,15 +7,15 @@
xmlns:avalonia_converters="using:Avalonia.Data.Converters"
xmlns:i="using:Avalonia.Xaml.Interactivity"
xmlns:ia="using:Avalonia.Xaml.Interactions.Custom"
xmlns:local="using:GSS2"
xmlns:controls="using:GSS2.Controls"
xmlns:core="using:GSS2.UI.Core"
xmlns:core_vm="using:GSS2.UI.Core.ViewModels"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:DataType="vm:SeparatorCalibrationViewModel">
<UserControl.Resources>
<converters:NotEqualsConverter x:Key="NotEqualsConverter" />
<converters:EqualsConverter x:Key="EqualsConverter" />
<converters:DateTimeConverter x:Key="DateTimeConverter" />
<SolidColorBrush x:Key="MenuBackground" Color="#00357a" />
<SolidColorBrush x:Key="MenuBorder" Color="#0865b2" />
@@ -53,6 +53,8 @@
<Style Selector="TextBox.multiline">
<Setter Property="VerticalContentAlignment" Value="Top" />
<Setter Property="AcceptsReturn" Value="True" />
<Setter Property="TextWrapping" Value="Wrap" />
</Style>
<Style Selector="TextBlock">
@@ -80,7 +82,7 @@
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" /> <!-- Удалить -->
<ColumnDefinition Width="*" /> <!-- Сохранить -->
<ColumnDefinition Width="*" /> <!-- К информации/К изображениям -->
<ColumnDefinition Width="*" /> <!-- К информации/К изображению -->
</Grid.ColumnDefinitions>
<!-- Главная панель -->
@@ -124,186 +126,60 @@
<!-- Тип (подпись) -->
<TextBlock Grid.Row="2" Grid.Column="1" Classes="mini" Text="Тип:" />
<!-- Тип (поле) -->
<local:TouchTextBox Grid.Row="3" Grid.Column="1" Classes="singleline" Text="{Binding EditingRecord.Type}" PlaceholderText="Тип" />
<controls:TouchTextBox Grid.Row="3" Grid.Column="1" Classes="singleline" Text="{Binding EditingRecord.Type}" PlaceholderText="Тип" />
<!-- Партия (подпись) -->
<TextBlock Grid.Row="4" Grid.Column="1" Classes="mini" Text="Партия:" />
<!-- Партия (поле) -->
<local:TouchTextBox Grid.Row="5" Grid.Column="1" Classes="singleline" Text="{Binding EditingRecord.Batch}" PlaceholderText="Партия" />
<controls:TouchTextBox Grid.Row="5" Grid.Column="1" Classes="singleline" Text="{Binding EditingRecord.Batch}" PlaceholderText="Партия" />
</Grid>
<!-- Изображения -->
<!-- Изображение -->
<Grid ColumnSpacing="5" RowSpacing="5">
<Grid.RowDefinitions>
<RowDefinition Height="*" /> <!-- Изображения -->
<RowDefinition Height="Auto" /> <!-- Кнопка "получить изображения" -->
<RowDefinition Height="*" /> <!-- Изображение -->
<RowDefinition Height="Auto" /> <!-- Кнопка "Получить изображения" / "Отменить съёмку" -->
</Grid.RowDefinitions>
<!-- Изображения -->
<Grid Grid.Row="0">
<!-- Изображение -->
<Grid>
<Grid ColumnSpacing="5">
<!-- Изображение -->
<Grid>
<Grid.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding
Converter="{StaticResource NotEqualsConverter}"
ConverterParameter="0"
Path="Images.Count" />
<Binding Converter="{x:Static ObjectConverters.IsNotNull}" Path="Image" />
<Binding Converter="{x:Static BoolConverters.Not}" Path="ImagesIsCapturing" />
</MultiBinding>
</Grid.IsVisible>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <!-- Кнопка влево -->
<ColumnDefinition Width="*" /> <!-- Изображения -->
<ColumnDefinition Width="Auto" /> <!-- Кнопка вправо -->
</Grid.ColumnDefinitions>
<!-- Изображение -->
<core:ZoomPanImage HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
ImageSource="{Binding Image.Image}"
Background="Black"
IsVisible="{Binding Image.IsLoading, Converter={x:Static BoolConverters.Not}}" />
<!-- Кнопка влево -->
<Button
Grid.Column="0"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Classes="vertical"
Command="{Binding ImagesSectionPreviousCommand}">
<TextBlock Text="◀"/>
<Button.IsEnabled>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="ImagesSectionCanScrollBackward" />
<Binding Converter="{x:Static BoolConverters.Not}" Path="ImagesSectionIsScrolling" />
</MultiBinding>
</Button.IsEnabled>
</Button>
<!-- Изображения -->
<core:SectionPanel
Grid.Column="1"
CanScrollBackward="{Binding ImagesSectionCanScrollBackward}"
CanScrollForward="{Binding ImagesSectionCanScrollForward}"
ChildrenSource="{Binding Images}"
ClipToBounds="True"
CurrentIndex="{Binding ImagesSectionCurrentIndex}"
Cyclic="True"
IsScrolling="{Binding ImagesSectionIsScrolling}"
Orientation="Horizontal">
<core:SectionPanel.ChildrenTemplate>
<DataTemplate>
<Grid ColumnSpacing="5" RowSpacing="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" /> <!-- Изображения -->
<ColumnDefinition Width="Auto" /> <!-- Информация -->
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <!-- Изображения -->
<RowDefinition Height="Auto" /> <!-- ИД (подпись) -->
<RowDefinition Height="Auto" /> <!-- ИД (поле) -->
<RowDefinition Height="Auto" /> <!-- Интенсивность видимого (подпись) -->
<RowDefinition Height="Auto" /> <!-- Интенсивность видимого (поле) -->
<RowDefinition Height="Auto" /> <!-- Интенсивность УФ 365 нм (подпись) -->
<RowDefinition Height="Auto" /> <!-- Интенсивность УФ 365 нм (поле) -->
<RowDefinition Height="Auto" /> <!-- Интенсивность УФ 254 нм (подпись) -->
<RowDefinition Height="Auto" /> <!-- Интенсивность УФ 254 нм (поле) -->
<RowDefinition Height="*" /> <!-- Пустое пространство -->
</Grid.RowDefinitions>
<!-- Изображения -->
<Grid Grid.Row="0" Grid.RowSpan="12" Grid.Column="0">
<core:ZoomPanImage
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="Black"
x:DataType="core_vm:AsyncImageRecordViewModel"
ImageSource="{Binding Image}"
IsVisible="{Binding IsLoading, Converter={x:Static BoolConverters.Not}}" />
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Center" x:DataType="core_vm:AsyncImageRecordViewModel" IsVisible="{Binding IsLoading}">
<ProgressBar IsIndeterminate="True" />
<TextBlock HorizontalAlignment="Center" Text="Изображение загружается" />
</StackPanel>
</Grid>
<!-- Информация -->
<!-- ИД (подпись) -->
<TextBlock Grid.Row="0" Grid.Column="1" Classes="mini" Text="ИД: " />
<!-- ИД (поле) -->
<TextBox Grid.Row="1" Grid.Column="1" Classes="singleline" IsReadOnly="True" x:DataType="core_vm:AsyncImageRecordViewModel" Text="{Binding ImageRecord.Id}" />
<!-- Интенсивность видимого (подпись) -->
<TextBlock Grid.Row="3" Grid.Column="1" Classes="mini" Text="Интенсивность видимого: " />
<!-- Интенсивность видимого (поле) -->
<TextBox Grid.Row="4" Grid.Column="1" Classes="singleline" IsReadOnly="True" x:DataType="core_vm:AsyncImageRecordViewModel" Text="{Binding ImageRecord.VisibleIntensity}" />
<!-- Интенсивность УФ 365 нм (подпись) -->
<TextBlock Grid.Row="5" Grid.Column="1" Classes="mini" Text="Интенсивность УФ 365 нм: " />
<!-- Интенсивность УФ 365 нм (поле) -->
<TextBox Grid.Row="6" Grid.Column="1" Classes="singleline" IsReadOnly="True" x:DataType="core_vm:AsyncImageRecordViewModel" Text="{Binding ImageRecord.Uv365Intensity}" />
<!-- Интенсивность УФ 254 нм (подпись) -->
<TextBlock Grid.Row="7" Grid.Column="1" Classes="mini" Text="Интенсивность УФ 254 нм: " />
<!-- Интенсивность УФ 254 нм (поле) -->
<TextBox Grid.Row="8" Grid.Column="1" Classes="singleline" IsReadOnly="True" x:DataType="core_vm:AsyncImageRecordViewModel" Text="{Binding ImageRecord.Uv254Intensity}" />
</Grid>
</DataTemplate>
</core:SectionPanel.ChildrenTemplate>
</core:SectionPanel>
<!-- Кнопка вправо -->
<Button
Grid.Column="2"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Classes="vertical"
Command="{Binding ImagesSectionNextCommand}">
<TextBlock Text="▶"/>
<Button.IsEnabled>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="ImagesSectionCanScrollForward" />
<Binding Converter="{x:Static BoolConverters.Not}" Path="ImagesSectionIsScrolling" />
</MultiBinding>
</Button.IsEnabled>
</Button>
<!-- Оверлей загрузки -->
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Center" IsVisible="{Binding Image.IsLoading}">
<ProgressBar IsIndeterminate="True" />
<TextBlock HorizontalAlignment="Center" Text="Изображение загружается" />
</StackPanel>
</Grid>
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="Изображения сепаратора отсутствуют">
<!-- Оверлей "Изображения отсутствуют" -->
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="Изображения отсутствуют">
<TextBlock.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding
Converter="{StaticResource EqualsConverter}"
ConverterParameter="0"
Path="Images.Count" />
<Binding Converter="{x:Static ObjectConverters.IsNull}" Path="Image" />
<Binding Converter="{x:Static BoolConverters.Not}" Path="ImagesIsCapturing" />
</MultiBinding>
</TextBlock.IsVisible>
</TextBlock>
<!-- Оверлей прогресс -->
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Center" IsVisible="{Binding ImagesIsCapturing}">
<ProgressBar IsIndeterminate="True" />
<TextBlock HorizontalAlignment="Center" Text="{Binding ImagesCapturingProgress}" />
@@ -311,20 +187,18 @@
</Grid>
<!-- Кнопка "получить изображения" -->
<Button
Grid.Row="1"
<!-- Кнопка "Получить изображения" -->
<Button Grid.Row="1"
HorizontalAlignment="Stretch"
Command="{Binding CaptureImageCommand}"
IsVisible="{Binding CaptureImagesTask, Converter={x:Static ObjectConverters.IsNull}}">
<TextBlock Text="Получить изображения"/>
</Button>
<Button
Grid.Row="1"
<!-- Кнопка "Отменить съёмку" -->
<Button Grid.Row="1"
HorizontalAlignment="Stretch"
Command="{Binding CancelImageCapturingCommand}"
Content="Отменить съёмку"
IsVisible="{Binding CaptureImagesTask, Converter={x:Static ObjectConverters.IsNotNull}}">
<TextBlock Text="Отменить съёмку"/>
</Button>
@@ -345,9 +219,7 @@
</Button>
<!-- К информации -->
<Button
Grid.Row="1"
Grid.Column="2"
<Button Grid.Row="1" Grid.Column="2"
HorizontalAlignment="Stretch"
Command="{Binding SwitchMainSectionCommand}"
Content="К информации"
@@ -364,16 +236,14 @@
</Button>
<!-- К изображениям -->
<Button
Grid.Row="1"
Grid.Column="2"
<!-- К изображению -->
<Button Grid.Row="1" Grid.Column="2"
HorizontalAlignment="Stretch"
Command="{Binding SwitchMainSectionCommand}"
Content="К изображениям"
Content="К изображению"
IsVisible="{Binding MainSectionCurrentIndex, Converter={StaticResource EqualsConverter}, ConverterParameter=0}">
<TextBlock Text="К изображениям"/>
<TextBlock Text="К изображению"/>
<Button.IsEnabled>
<MultiBinding Converter="{x:Static BoolConverters.And}">
@@ -396,13 +266,9 @@
</Border>
<!-- Выезжающая боковая панель -->
<Border
HorizontalAlignment="Left"
Background="{StaticResource MenuBackground}"
BorderBrush="{StaticResource MenuBorder}"
BorderThickness="0,0,1,0"
IsEnabled="{Binding MenuOpened}"
IsVisible="{Binding MenuOpened}">
<Border HorizontalAlignment="Left"
Background="{StaticResource MenuBackground}" BorderBrush="{StaticResource MenuBorder}" BorderThickness="0,0,1,0"
IsEnabled="{Binding MenuOpened}" IsVisible="{Binding MenuOpened}">
<Border.Transitions>
<Transitions>
@@ -412,22 +278,12 @@
<Interaction.Behaviors>
<DataTriggerBehavior
Binding="{Binding MenuOpened}"
ComparisonCondition="Equal"
Value="True">
<DataTriggerBehavior Binding="{Binding MenuOpened}" ComparisonCondition="Equal" Value="True">
<ChangePropertyAction PropertyName="RenderTransform" Value="translateX(0px)" />
</DataTriggerBehavior>
<DataTriggerBehavior
Binding="{Binding MenuOpened}"
ComparisonCondition="Equal"
Value="False">
<DataTriggerBehavior Binding="{Binding MenuOpened}" ComparisonCondition="Equal" Value="False">
<ChangePropertyAction PropertyName="RenderTransform" Value="translateX(-320px)" />
</DataTriggerBehavior>
</Interaction.Behaviors>
@@ -440,14 +296,11 @@
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Grid.Row="0"
MinWidth="200"
HorizontalAlignment="Stretch"
Command="{Binding CreateRecordCommand}">
<Button Grid.Row="0" MinWidth="200" HorizontalAlignment="Stretch" Command="{Binding CreateRecordCommand}">
<TextBlock Text="Новая запись"/>
</Button>
<ListBox Grid.Row="1" ItemsSource="{Binding Records}" SelectedItem="{Binding SelectedRecord}">
<ListBox Grid.Row="1" Background="{StaticResource MenuBackground}" ItemsSource="{Binding Records}" SelectedItem="{Binding SelectedRecord}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>