更新202612

This commit is contained in:
GukSang.Jin
2026-05-20 13:33:15 +08:00
parent 43893e5da6
commit 17d9904898
7 changed files with 250 additions and 30 deletions

View File

@@ -84,5 +84,16 @@ namespace TabletTester2025.Services
query = query.OrderByDescending(b => b.TestTime).Take(limit); query = query.OrderByDescending(b => b.TestTime).Take(limit);
return query.ToList(); return query.ToList();
} }
public void DeleteBatch(int id)
{
using var db = new AppDbContext(_connectionString);
var batch = db.TestBatches.Find(id);
if (batch != null)
{
db.TestBatches.Remove(batch);
db.SaveChanges();
}
}
} }
} }

View File

@@ -60,7 +60,7 @@ namespace TabletTester2025.Services
{ {
var data = batches.ToList(); var data = batches.ToList();
var sheet = package.Workbook.Worksheets.Add("硬度报表"); var sheet = package.Workbook.Worksheets.Add("硬度报表");
WriteHeader(sheet, "检测时间", "样品名称", "平均值(N)", "平均偏差(N)", "RSD(%)", "最大值(N)", "最小值(N)", "测试次数", "单次数据(N)", "内控下限(N)", "内控上限(N)", "判定"); WriteHeader(sheet, "检测时间", "样品名称", "平均值(N)", "平均偏差(N)", "RSD(%)", "最大值(N)", "最小值(N)", "测试次数", "单次数据(N)", "判定");
if (data.Count == 0) if (data.Count == 0)
{ {
@@ -81,9 +81,7 @@ namespace TabletTester2025.Services
sheet.Cells[row, 7].Value = b.HardnessMin; sheet.Cells[row, 7].Value = b.HardnessMin;
sheet.Cells[row, 8].Value = b.HardnessTestCount; sheet.Cells[row, 8].Value = b.HardnessTestCount;
sheet.Cells[row, 9].Value = b.HardnessSampleSummary; sheet.Cells[row, 9].Value = b.HardnessSampleSummary;
sheet.Cells[row, 10].Value = b.HardnessInternalMin; sheet.Cells[row, 10].Value = b.HardnessPassText;
sheet.Cells[row, 11].Value = b.HardnessInternalMax;
sheet.Cells[row, 12].Value = b.HardnessPassText;
row++; row++;
} }
@@ -150,7 +148,7 @@ namespace TabletTester2025.Services
{ {
var data = batches.ToList(); var data = batches.ToList();
var sheet = package.Workbook.Worksheets.Add("崩解报表"); var sheet = package.Workbook.Worksheets.Add("崩解报表");
WriteHeader(sheet, "检测时间", "样品名称", "剂型规格", "时限(秒)", "崩解时间(秒)", "剩余未崩解管", "水浴温度(℃)", "判定"); WriteHeader(sheet, "检测时间", "样品名称", "崩解时间(秒)", "水浴温度(℃)", "判定");
if (data.Count == 0) if (data.Count == 0)
{ {
@@ -164,12 +162,9 @@ namespace TabletTester2025.Services
{ {
sheet.Cells[row, 1].Value = b.TestTime.ToString("yyyy-MM-dd HH:mm:ss"); sheet.Cells[row, 1].Value = b.TestTime.ToString("yyyy-MM-dd HH:mm:ss");
sheet.Cells[row, 2].Value = b.SampleName; sheet.Cells[row, 2].Value = b.SampleName;
sheet.Cells[row, 3].Value = b.DisintegrationDosageForm; sheet.Cells[row, 3].Value = b.DisintegrationTimeSec;
sheet.Cells[row, 4].Value = b.DisintegrationLimitSeconds; sheet.Cells[row, 4].Value = b.DisintegrationTemp;
sheet.Cells[row, 5].Value = b.DisintegrationTimeSec; sheet.Cells[row, 5].Value = b.DisintegrationPassText;
sheet.Cells[row, 6].Value = b.RemainingTubesAtEnd;
sheet.Cells[row, 7].Value = b.DisintegrationTemp;
sheet.Cells[row, 8].Value = b.DisintegrationPassText;
row++; row++;
} }

View File

@@ -14,6 +14,13 @@ namespace TabletTester2025.ViewModels
private double _groupAverageDeviation; private double _groupAverageDeviation;
private double _groupRSD; private double _groupRSD;
private DateTime _recordedAt; private DateTime _recordedAt;
private bool _isSummaryRow;
public bool IsSummaryRow
{
get => _isSummaryRow;
set => SetProperty(ref _isSummaryRow, value);
}
public int GroupNo public int GroupNo
{ {

View File

@@ -1625,6 +1625,7 @@ namespace TabletTester2025.ViewModels
throw new InvalidOperationException("硬度测试已停止,未保存结果"); throw new InvalidOperationException("硬度测试已停止,未保存结果");
ApplyHardnessStatistics(count); ApplyHardnessStatistics(count);
AddHardnessGroupSummaryRow();
resultReady = true; resultReady = true;
} }
catch (Exception ex) catch (Exception ex)
@@ -1775,6 +1776,29 @@ namespace TabletTester2025.ViewModels
} }
} }
private void AddHardnessGroupSummaryRow()
{
var stats = TestCalculationService.CalculateHardness(
_hardnessResults,
HardnessInternalMin,
HardnessInternalMax,
_hardnessResults.Count);
HardnessDisplaySamplePoints.Add(new HardnessDisplaySamplePoint
{
IsSummaryRow = true,
GroupNo = _currentHardnessGroupNo,
CumulativeNo = 0,
SequenceNo = 0,
Value = 0,
DeviationFromAverage = 0,
GroupAverage = stats.Average,
GroupAverageDeviation = stats.AverageDeviation,
GroupRSD = stats.RsdPercent,
RecordedAt = DateTime.MinValue
});
}
/// 脆碎度测试主逻辑(实时状态显示) /// 脆碎度测试主逻辑(实时状态显示)
private async Task RunFriabilityAsync() private async Task RunFriabilityAsync()

View File

@@ -94,6 +94,28 @@
</Setter> </Setter>
</Style> </Style>
<Style TargetType="Button" x:Key="DangerButton" BasedOn="{StaticResource ActionButton}">
<Setter Property="Background" Value="#DC2626"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="BorderBrush" Value="#DC2626"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}" CornerRadius="6"
BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1"
Padding="12,0">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#B91C1C"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- TabControl 样式 --> <!-- TabControl 样式 -->
<Style TargetType="TabControl"> <Style TargetType="TabControl">
<Setter Property="Background" Value="Transparent"/> <Setter Property="Background" Value="Transparent"/>
@@ -163,8 +185,12 @@
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
<RowDefinition Height="*"/> <RowDefinition Height="*"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Button Grid.Row="0" Content="📎 导出硬度报表" Style="{StaticResource ExportButton}" <StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,0,0,12">
Width="140" HorizontalAlignment="Right" Margin="0,0,0,12" Click="ExportHardness_Click"/> <Button Content="🗑️ 删除选中" Style="{StaticResource DangerButton}"
Width="120" Margin="0,0,8,0" Click="DeleteHardness_Click"/>
<Button Content="📎 导出硬度报表" Style="{StaticResource ExportButton}"
Width="140" Click="ExportHardness_Click"/>
</StackPanel>
<DataGrid x:Name="HardnessGrid" Grid.Row="1"> <DataGrid x:Name="HardnessGrid" Grid.Row="1">
<DataGrid.Columns> <DataGrid.Columns>
<DataGridTextColumn Header="检测时间" Binding="{Binding TestTime, StringFormat=yyyy-MM-dd HH:mm:ss}" Width="160"/> <DataGridTextColumn Header="检测时间" Binding="{Binding TestTime, StringFormat=yyyy-MM-dd HH:mm:ss}" Width="160"/>
@@ -176,8 +202,6 @@
<DataGridTextColumn Header="最小值(N)" Binding="{Binding HardnessMin, StringFormat=F1}" Width="90"/> <DataGridTextColumn Header="最小值(N)" Binding="{Binding HardnessMin, StringFormat=F1}" Width="90"/>
<DataGridTextColumn Header="测试次数" Binding="{Binding HardnessTestCount}" Width="70"/> <DataGridTextColumn Header="测试次数" Binding="{Binding HardnessTestCount}" Width="70"/>
<DataGridTextColumn Header="单次数据(N)" Binding="{Binding HardnessSampleSummary}" Width="220"/> <DataGridTextColumn Header="单次数据(N)" Binding="{Binding HardnessSampleSummary}" Width="220"/>
<DataGridTextColumn Header="内控下限(N)" Binding="{Binding HardnessInternalMin, StringFormat=F1}" Width="100"/>
<DataGridTextColumn Header="内控上限(N)" Binding="{Binding HardnessInternalMax, StringFormat=F1}" Width="100"/>
<DataGridTextColumn Header="判定" Binding="{Binding HardnessPassText}" Width="70"/> <DataGridTextColumn Header="判定" Binding="{Binding HardnessPassText}" Width="70"/>
</DataGrid.Columns> </DataGrid.Columns>
</DataGrid> </DataGrid>
@@ -191,8 +215,12 @@
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
<RowDefinition Height="*"/> <RowDefinition Height="*"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Button Grid.Row="0" Content="📎 导出脆碎度报表" Style="{StaticResource ExportButton}" <StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,0,0,12">
Width="150" HorizontalAlignment="Right" Margin="0,0,0,12" Click="ExportFriability_Click"/> <Button Content="🗑️ 删除选中" Style="{StaticResource DangerButton}"
Width="120" Margin="0,0,8,0" Click="DeleteFriability_Click"/>
<Button Content="📎 导出脆碎度报表" Style="{StaticResource ExportButton}"
Width="150" Click="ExportFriability_Click"/>
</StackPanel>
<DataGrid x:Name="FriabilityGrid" Grid.Row="1"> <DataGrid x:Name="FriabilityGrid" Grid.Row="1">
<DataGrid.Columns> <DataGrid.Columns>
<DataGridTextColumn Header="检测时间" Binding="{Binding TestTime, StringFormat=yyyy-MM-dd HH:mm:ss}" Width="160"/> <DataGridTextColumn Header="检测时间" Binding="{Binding TestTime, StringFormat=yyyy-MM-dd HH:mm:ss}" Width="160"/>
@@ -216,16 +244,17 @@
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
<RowDefinition Height="*"/> <RowDefinition Height="*"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Button Grid.Row="0" Content="📎 导出崩解报表" Style="{StaticResource ExportButton}" <StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,0,0,12">
Width="150" HorizontalAlignment="Right" Margin="0,0,0,12" Click="ExportDisintegration_Click"/> <Button Content="🗑️ 删除选中" Style="{StaticResource DangerButton}"
Width="120" Margin="0,0,8,0" Click="DeleteDisintegration_Click"/>
<Button Content="📎 导出崩解报表" Style="{StaticResource ExportButton}"
Width="150" Click="ExportDisintegration_Click"/>
</StackPanel>
<DataGrid x:Name="DisintegrationGrid" Grid.Row="1"> <DataGrid x:Name="DisintegrationGrid" Grid.Row="1">
<DataGrid.Columns> <DataGrid.Columns>
<DataGridTextColumn Header="检测时间" Binding="{Binding TestTime, StringFormat=yyyy-MM-dd HH:mm:ss}" Width="160"/> <DataGridTextColumn Header="检测时间" Binding="{Binding TestTime, StringFormat=yyyy-MM-dd HH:mm:ss}" Width="160"/>
<DataGridTextColumn Header="样品名称" Binding="{Binding SampleName}" Width="120"/> <DataGridTextColumn Header="样品名称" Binding="{Binding SampleName}" Width="120"/>
<DataGridTextColumn Header="剂型规格" Binding="{Binding DisintegrationDosageForm}" Width="100"/>
<DataGridTextColumn Header="时限(秒)" Binding="{Binding DisintegrationLimitSeconds}" Width="80"/>
<DataGridTextColumn Header="崩解时间(秒)" Binding="{Binding DisintegrationTimeSec}" Width="100"/> <DataGridTextColumn Header="崩解时间(秒)" Binding="{Binding DisintegrationTimeSec}" Width="100"/>
<DataGridTextColumn Header="剩余未崩解管" Binding="{Binding RemainingTubesAtEnd}" Width="110"/>
<DataGridTextColumn Header="水浴温度(℃)" Binding="{Binding DisintegrationTemp, StringFormat=F1}" Width="110"/> <DataGridTextColumn Header="水浴温度(℃)" Binding="{Binding DisintegrationTemp, StringFormat=F1}" Width="110"/>
<DataGridTextColumn Header="判定" Binding="{Binding DisintegrationPassText}" Width="70"/> <DataGridTextColumn Header="判定" Binding="{Binding DisintegrationPassText}" Width="70"/>
</DataGrid.Columns> </DataGrid.Columns>
@@ -240,8 +269,12 @@
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
<RowDefinition Height="*"/> <RowDefinition Height="*"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Button Grid.Row="0" Content="📎 导出溶出报表" Style="{StaticResource ExportButton}" <StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,0,0,12">
Width="150" HorizontalAlignment="Right" Margin="0,0,0,12" Click="ExportDissolution_Click"/> <Button Content="🗑️ 删除选中" Style="{StaticResource DangerButton}"
Width="120" Margin="0,0,8,0" Click="DeleteDissolution_Click"/>
<Button Content="📎 导出溶出报表" Style="{StaticResource ExportButton}"
Width="150" Click="ExportDissolution_Click"/>
</StackPanel>
<DataGrid x:Name="DissolutionGrid" Grid.Row="1"> <DataGrid x:Name="DissolutionGrid" Grid.Row="1">
<DataGrid.Columns> <DataGrid.Columns>
<DataGridTextColumn Header="检测时间" Binding="{Binding TestTime, StringFormat=yyyy-MM-dd HH:mm:ss}" Width="160"/> <DataGridTextColumn Header="检测时间" Binding="{Binding TestTime, StringFormat=yyyy-MM-dd HH:mm:ss}" Width="160"/>

View File

@@ -43,6 +43,66 @@ namespace TabletTester2025
LoadData(); LoadData();
} }
private void DeleteHardness_Click(object sender, RoutedEventArgs e)
{
if (HardnessGrid.SelectedItem is not TestBatch batch)
{
MessageBox.Show("请先选择一条记录", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
var result = MessageBox.Show($"确定要删除该记录吗?\n检测时间{batch.TestTime:yyyy-MM-dd HH:mm:ss}",
"确认删除", MessageBoxButton.YesNo, MessageBoxImage.Warning);
if (result != MessageBoxResult.Yes)
return;
_dbService.DeleteBatch(batch.Id);
LoadData();
}
private void DeleteFriability_Click(object sender, RoutedEventArgs e)
{
if (FriabilityGrid.SelectedItem is not TestBatch batch)
{
MessageBox.Show("请先选择一条记录", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
var result = MessageBox.Show($"确定要删除该记录吗?\n检测时间{batch.TestTime:yyyy-MM-dd HH:mm:ss}",
"确认删除", MessageBoxButton.YesNo, MessageBoxImage.Warning);
if (result != MessageBoxResult.Yes)
return;
_dbService.DeleteBatch(batch.Id);
LoadData();
}
private void DeleteDisintegration_Click(object sender, RoutedEventArgs e)
{
if (DisintegrationGrid.SelectedItem is not TestBatch batch)
{
MessageBox.Show("请先选择一条记录", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
var result = MessageBox.Show($"确定要删除该记录吗?\n检测时间{batch.TestTime:yyyy-MM-dd HH:mm:ss}",
"确认删除", MessageBoxButton.YesNo, MessageBoxImage.Warning);
if (result != MessageBoxResult.Yes)
return;
_dbService.DeleteBatch(batch.Id);
LoadData();
}
private void DeleteDissolution_Click(object sender, RoutedEventArgs e)
{
if (DissolutionGrid.SelectedItem is not TestBatch batch)
{
MessageBox.Show("请先选择一条记录", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
var result = MessageBox.Show($"确定要删除该记录吗?\n检测时间{batch.TestTime:yyyy-MM-dd HH:mm:ss}",
"确认删除", MessageBoxButton.YesNo, MessageBoxImage.Warning);
if (result != MessageBoxResult.Yes)
return;
_dbService.DeleteBatch(batch.Id);
LoadData();
}
private void ExportHardness_Click(object sender, RoutedEventArgs e) private void ExportHardness_Click(object sender, RoutedEventArgs e)
{ {
var data = HardnessGrid.ItemsSource as IEnumerable<TestBatch>; var data = HardnessGrid.ItemsSource as IEnumerable<TestBatch>;

View File

@@ -353,16 +353,106 @@
MinHeight="160" MinHeight="160"
ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Auto"> ScrollViewer.HorizontalScrollBarVisibility="Auto">
<DataGrid.RowStyle>
<Style TargetType="DataGridRow" BasedOn="{StaticResource {x:Type DataGridRow}}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSummaryRow}" Value="True">
<Setter Property="Background" Value="#DBEAFE"/>
<Setter Property="FontWeight" Value="Bold"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
<DataGrid.Columns> <DataGrid.Columns>
<DataGridTextColumn Header="累计次数" Binding="{Binding CumulativeNo}" Width="85"/> <DataGridTemplateColumn Header="累计次数" Width="85">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding CumulativeNo}" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSummaryRow}" Value="True">
<Setter Property="Text" Value=""/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="组号" Binding="{Binding GroupNo}" Width="65"/> <DataGridTextColumn Header="组号" Binding="{Binding GroupNo}" Width="65"/>
<DataGridTextColumn Header="组内序号" Binding="{Binding SequenceNo}" Width="80"/> <DataGridTemplateColumn Header="组内序号" Width="80">
<DataGridTextColumn Header="硬度值(N)" Binding="{Binding Value, StringFormat=F1}" Width="95"/> <DataGridTemplateColumn.CellTemplate>
<DataGridTextColumn Header="与平均值偏差(N)" Binding="{Binding DeviationFromAverage, StringFormat=F2}" Width="125"/> <DataTemplate>
<TextBlock Text="{Binding SequenceNo}" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSummaryRow}" Value="True">
<Setter Property="Text" Value=""/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="硬度值(N)" Width="95">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Value, StringFormat=F1}" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSummaryRow}" Value="True">
<Setter Property="Text" Value=""/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="与平均值偏差(N)" Width="125">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding DeviationFromAverage, StringFormat=F2}" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSummaryRow}" Value="True">
<Setter Property="Text" Value=""/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="组平均值(N)" Binding="{Binding GroupAverage, StringFormat=F1}" Width="105"/> <DataGridTextColumn Header="组平均值(N)" Binding="{Binding GroupAverage, StringFormat=F1}" Width="105"/>
<DataGridTextColumn Header="组平均偏差(N)" Binding="{Binding GroupAverageDeviation, StringFormat=F2}" Width="120"/> <DataGridTextColumn Header="组平均偏差(N)" Binding="{Binding GroupAverageDeviation, StringFormat=F2}" Width="120"/>
<DataGridTextColumn Header="组RSD(%)" Binding="{Binding GroupRSD, StringFormat=F2}" Width="95"/> <DataGridTextColumn Header="组RSD(%)" Binding="{Binding GroupRSD, StringFormat=F2}" Width="95"/>
<DataGridTextColumn Header="记录时间" Binding="{Binding RecordedAt, StringFormat=HH:mm:ss}" Width="105"/> <DataGridTemplateColumn Header="记录时间" Width="105">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding RecordedAt, StringFormat=HH:mm:ss}" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSummaryRow}" Value="True">
<Setter Property="Text" Value=""/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns> </DataGrid.Columns>
</DataGrid> </DataGrid>
</Grid> </Grid>