This commit is contained in:
xyy
2026-05-15 10:59:24 +08:00
parent 213946642e
commit 873dbe61bb
3 changed files with 232 additions and 118 deletions

View File

@@ -11,6 +11,7 @@
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.2" />
<PackageReference Include="OxyPlot.Wpf" Version="2.2.0" />
</ItemGroup>
<ItemGroup>

View File

@@ -1,14 +1,17 @@
using System;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Windows;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using ASTM_D7896_Tester.Helpers;
using ASTM_D7896_Tester.Models;
using ASTM_D7896_Tester.Services;
using ASTM_D7896_Tester.Helpers;
using System.Linq;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using OxyPlot;
using OxyPlot.Axes;
using OxyPlot.Series;
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace ASTM_D7896_Tester.ViewModels;
@@ -89,6 +92,31 @@ public partial class D7896ViewModel : ObservableObject
[ObservableProperty]
private double _calibrationErrorPercent = 0.0;
// 新增核心参数(实时显示)
[ObservableProperty]
private double _platinumVoltage; // 铂丝电压 U_pt (V)
[ObservableProperty]
private double _standardResistorVoltage; // 标准电阻电压 U_std (V)
[ObservableProperty]
private double _platinumResistance; // 铂丝电阻 R_pt (Ω)
[ObservableProperty]
private double _chamberPressure; // 样品池压力 (kPa)
// 当前曲线标题
[ObservableProperty]
private string _curveTitle = "温升曲线";
// 在 ViewModel 中
[ObservableProperty]
private PlotModel _temperatureCurveModel;
public D7896ViewModel()
{
_config = JsonConfigHelper.LoadConfig();
@@ -101,6 +129,10 @@ public partial class D7896ViewModel : ObservableObject
PressureValue = _config.TestParameters.DefaultPressure;
SelectedReferenceLiquid = _config.TestParameters.ReferenceLiquid;
ReferenceConductivity = _config.TestParameters.ReferenceConductivity;
IsCleanConfirmed = true;
BubbleRemoved = true;
PlatinumCompatible = true;
AmbientCalibrated = true;
}
// ========== 原有命令 ==========
@@ -177,7 +209,7 @@ public partial class D7896ViewModel : ObservableObject
float temperature = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.TestTemperature);
if (i == 1) TestTemperature = temperature;
GenerateTemperatureCurve(lambda, alpha); // 更新曲线图
var result = new MeasurementResult
{
Index = i,
@@ -199,6 +231,7 @@ public partial class D7896ViewModel : ObservableObject
}
}
CalculateAverages();
StatusMessage = "测试完成。";
}
@@ -214,6 +247,85 @@ public partial class D7896ViewModel : ObservableObject
}
}
// 模拟获取实时核心参数实际应从PLC读取
private async Task UpdateRealTimeParametersAsync()
{
if (await _plcService.IsConnectedAsync())
{
// 示例从PLC读取这些值地址需在配置文件中定义
PlatinumVoltage = await _plcService.ReadFloatAsync(40010); // 假设地址
StandardResistorVoltage = await _plcService.ReadFloatAsync(40012);
PlatinumResistance = await _plcService.ReadFloatAsync(40014);
ChamberPressure = await _plcService.ReadFloatAsync(40016);
}
}
private void GenerateTemperatureCurve(float lambda, float alpha)
{
// 第一次调用时初始化 PlotModel只创建一次
if (TemperatureCurveModel == null)
{
TemperatureCurveModel = new PlotModel
{
Title = "温升曲线对比 (10次测量)",
Background = OxyColors.White
};
// 添加坐标轴(只添加一次)
TemperatureCurveModel.Axes.Add(new LinearAxis
{
Position = AxisPosition.Bottom,
Title = "时间 (s)",
Minimum = 0,
Maximum = 2
});
TemperatureCurveModel.Axes.Add(new LinearAxis
{
Position = AxisPosition.Left,
Title = "温升 (℃)",
Minimum = 0
});
}
// 创建本次测量的曲线系列(用不同颜色区分)
var series = new LineSeries
{
Title = $"第{CurrentMeasurementIndex}次测量",
Color = GetColorForIndex(CurrentMeasurementIndex),
StrokeThickness = 1.5,
MarkerType = MarkerType.None
};
// 添加数据点(这里仍用模拟数据,实际应替换为真实采集数据)
// 理论公式ΔT = (Q/(4πλL)) * ln(t/t0) + C
// 其中 Q 是加热功率L 是铂丝长度C 是常数
double Q = 0.01; // 假设 10mW实际应从电流和电阻计算
double L = 0.04; // 40mm
double constant = 0.2;
for (int i = 0; i <= 200; i++)
{
double t = i * 0.01;
double deltaT = (Q / (4 * Math.PI * lambda * L)) * Math.Log(t + 0.1) + constant;
series.Points.Add(new DataPoint(t, deltaT));
}
// 将本次曲线添加到同一个 Model 中(叠加)
TemperatureCurveModel.Series.Add(series);
TemperatureCurveModel.InvalidatePlot(true);
CurveTitle = $"已完成 {CurrentMeasurementIndex} 次测量";
}
// 辅助方法:根据测量序号返回不同的颜色
private OxyColor GetColorForIndex(int index)
{
var colors = new[]
{
OxyColors.Red, OxyColors.Blue, OxyColors.Green, OxyColors.Orange,
OxyColors.Purple, OxyColors.Brown, OxyColors.Pink, OxyColors.Cyan,
OxyColors.Magenta, OxyColors.Olive
};
return colors[(index - 1) % colors.Length];
}
private void CalculateAverages()
{
if (Measurements.Count == 0) return;
@@ -232,12 +344,9 @@ public partial class D7896ViewModel : ObservableObject
CurrentMeasurementIndex = 0;
StatusMessage = "已重置";
TestDateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
TemperatureCurveModel = null; // 下次测量会重新初始化
// 重置确认标志(可根据需要决定是否重置)
// IsCleanConfirmed = false;
// BubbleRemoved = false;
// PlatinumCompatible = false;
// AmbientCalibrated = false;
}
[RelayCommand]
@@ -377,5 +486,14 @@ public partial class D7896ViewModel : ObservableObject
{
IsCalibrating = false;
}
}
}

View File

@@ -1,6 +1,7 @@
<UserControl x:Class="ASTM_D7896_Tester.Views.D7896View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:oxy="http://oxyplot.org/wpf"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
@@ -103,8 +104,9 @@
<!-- <converters:InverseBooleanConverter x:Key="InverseBooleanConverter"/> -->
</UserControl.Resources>
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" Background="#F2F2F2">
<Grid Margin="15">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
@@ -113,145 +115,138 @@
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 样品基本信息栏(卡片 -->
<Border Grid.Row="0" Background="White" CornerRadius="6" Padding="12" Margin="0,0,0,10" Effect="{StaticResource CardShadow}">
<WrapPanel>
<!-- 1. 样品信息 + 复选框合并的4项确认 -->
<Border Grid.Row="0" Background="White" CornerRadius="6" Padding="10" Margin="0,0,0,8" Effect="{StaticResource CardShadow}">
<StackPanel>
<WrapPanel Margin="0,0,0,8">
<TextBlock Text="样品ID:" VerticalAlignment="Center" FontWeight="SemiBold" Margin="0,0,8,0"/>
<TextBox Text="{Binding SampleId}" Width="140" Margin="0,0,25,0"/>
<TextBox Text="{Binding SampleId}" Width="120" Margin="0,0,20,0"/>
<TextBlock Text="测试温度(℃):" VerticalAlignment="Center" FontWeight="SemiBold" Margin="0,0,8,0"/>
<TextBox Text="{Binding TestTemperature}" Width="70" IsReadOnly="True" Background="#F0F8FF" Margin="0,0,25,0"/>
<TextBox Text="{Binding TestTemperature}" Width="70" IsReadOnly="True" Background="#F0F8FF" Margin="0,0,20,0"/>
<TextBlock Text="日期:" VerticalAlignment="Center" FontWeight="SemiBold" Margin="0,0,8,0"/>
<TextBox Text="{Binding TestDateTime}" Width="150" IsReadOnly="True" Background="#F0F8FF" Margin="0,0,25,0"/>
<TextBlock Text="状态:" VerticalAlignment="Center" FontWeight="SemiBold" Margin="0,0,8,0"/>
<TextBox Text="{Binding StatusMessage}" Width="210" IsReadOnly="True" Background="#FFF7E6"/>
<TextBox Text="{Binding TestDateTime}" Width="140" IsReadOnly="True" Background="#F0F8FF"/>
</WrapPanel>
</Border>
<!-- 样品体积卡片 -->
<Border Grid.Row="1" Background="White" CornerRadius="6" Padding="12" Margin="0,5" Effect="{StaticResource CardShadow}">
<WrapPanel>
<TextBlock Text="样品体积 (mL) [7.5]:" VerticalAlignment="Center" Width="140" FontWeight="SemiBold"/>
<TextBox Text="{Binding SampleVolume}" Width="80" Margin="5,0"/>
<TextBlock Text="标准要求约40 mL" Foreground="#777777" VerticalAlignment="Center" Margin="15,0,0,0"/>
<!-- 四个确认复选框,默认勾选 -->
<CheckBox IsChecked="{Binding IsCleanConfirmed}" Content="采样池清洁 (7.1)" Margin="0,0,15,0"/>
<CheckBox IsChecked="{Binding BubbleRemoved}" Content="气泡清除 (7.6)" Margin="0,0,15,0"/>
<CheckBox IsChecked="{Binding PlatinumCompatible}" Content="铂兼容性 (1.4)" Margin="0,0,15,0"/>
<CheckBox IsChecked="{Binding AmbientCalibrated}" Content="环境温度校准 (8.1)" Margin="0,0,15,0"/>
<TextBlock Text="状态:" VerticalAlignment="Center" Margin="20,0,5,0"/>
<TextBox Text="{Binding StatusMessage}" Width="200" IsReadOnly="True" Background="#FFF7E6"/>
</WrapPanel>
</StackPanel>
</Border>
<!-- 合规性确认区域(卡片 -->
<Border Grid.Row="2" Background="White" CornerRadius="6" Padding="12" Margin="0,5" Effect="{StaticResource CardShadow}">
<StackPanel>
<TextBlock Text="测试前确认(依据 ASTM D7896-19" FontWeight="Bold" FontSize="14" Margin="0,0,0,12" Foreground="#1E4F7A"/>
<!-- 2. 核心参数仪表盘(温度、电压、电阻、压力 -->
<Border Grid.Row="1" Background="White" CornerRadius="6" Padding="10" Margin="0,5" Effect="{StaticResource CardShadow}">
<WrapPanel>
<!-- 清洁确认 -->
<Border BorderBrush="#DDDDDD" BorderThickness="1" Padding="8" Margin="0,0,12,0" Width="210" CornerRadius="4" Background="#FEFEFE">
<StackPanel>
<TextBlock Text="章节7.1:采样池清洁" FontWeight="SemiBold" Margin="0,0,0,6"/>
<TextBox Text="{Binding CleanerName}" Width="120" Margin="0,4" ToolTip="请输入清洁人姓名"/>
<Button Content="确认清洁" Command="{Binding ConfirmCleanCommand}" Margin="0,4" Width="100"/>
<TextBlock Text="{Binding IsCleanConfirmed, StringFormat='已确认: {0}'}" FontSize="11" TextAlignment="Center" Margin="0,4"/>
<Border Background="#E8F0FE" Padding="6" CornerRadius="4" Margin="0,0,15,0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="🌡️ 样品温度:" FontWeight="SemiBold" Margin="0,0,5,0"/>
<TextBox Text="{Binding TestTemperature, StringFormat=F2}" Width="60" IsReadOnly="True"/>
<TextBlock Text="℃" Margin="3,0,0,0"/>
</StackPanel>
</Border>
<!-- 排气泡确认 -->
<Border BorderBrush="#DDDDDD" BorderThickness="1" Padding="8" Margin="0,0,12,0" Width="210" CornerRadius="4" Background="#FEFEFE">
<StackPanel>
<TextBlock Text="章节7.6:清除气泡" FontWeight="SemiBold" Margin="0,0,0,6"/>
<Button Content="确认已清除气泡" Command="{Binding ConfirmBubbleRemovedCommand}" Margin="0,8" Width="120"/>
<TextBlock Text="{Binding BubbleRemoved, StringFormat='已确认: {0}'}" FontSize="11" TextAlignment="Center" Margin="0,4"/>
<Border Background="#E8F0FE" Padding="6" CornerRadius="4" Margin="0,0,15,0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="⚡ 铂丝电压:" FontWeight="SemiBold" Margin="0,0,5,0"/>
<TextBox Text="{Binding PlatinumVoltage, StringFormat=F4}" Width="70" IsReadOnly="True"/>
<TextBlock Text="V" Margin="3,0,0,0"/>
</StackPanel>
</Border>
<!-- 铂兼容性 -->
<Border BorderBrush="#DDDDDD" BorderThickness="1" Padding="8" Margin="0,0,12,0" Width="210" CornerRadius="4" Background="#FEFEFE">
<StackPanel>
<TextBlock Text="章节1.4:铂反应性" FontWeight="SemiBold" Margin="0,0,0,6"/>
<Button Content="确认液体与铂兼容" Command="{Binding ConfirmPlatinumCompatibleCommand}" Margin="0,4" Width="132"/>
<TextBox Text="{Binding LiquidReactivityNote}" Width="120" Margin="0,4" ToolTip="备注(可选)"/>
<TextBlock Text="{Binding PlatinumCompatible, StringFormat='已确认: {0}'}" FontSize="11" TextAlignment="Center"/>
<Border Background="#E8F0FE" Padding="6" CornerRadius="4" Margin="0,0,15,0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="🔌 铂丝电阻:" FontWeight="SemiBold" Margin="0,0,5,0"/>
<TextBox Text="{Binding PlatinumResistance, StringFormat=F4}" Width="70" IsReadOnly="True"/>
<TextBlock Text="Ω" Margin="3,0,0,0"/>
</StackPanel>
</Border>
<!-- 环境温度校准 -->
<Border BorderBrush="#DDDDDD" BorderThickness="1" Padding="8" Width="210" CornerRadius="4" Background="#FEFEFE">
<StackPanel>
<TextBlock Text="章节8.1:环境温度校准" FontWeight="SemiBold" Margin="0,0,0,6"/>
<Button Content="开始校准" Command="{Binding CalibrateAmbientCommand}" Margin="0,8" Width="100"/>
<TextBlock Text="{Binding AmbientTemperature, StringFormat='温度: {0:F1} °C'}" TextAlignment="Center" Margin="0,4"/>
<TextBlock Text="{Binding AmbientCalibrated, StringFormat='校准状态: {0}'}" FontSize="11" TextAlignment="Center"/>
<Border Background="#E8F0FE" Padding="6" CornerRadius="4" Margin="0,0,15,0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="⏲️ 压力:" FontWeight="SemiBold" Margin="0,0,5,0"/>
<TextBox Text="{Binding ChamberPressure, StringFormat=F1}" Width="60" IsReadOnly="True"/>
<TextBlock Text="kPa" Margin="3,0,0,0"/>
</StackPanel>
</Border>
</WrapPanel>
</StackPanel>
</Border>
<!-- 加压设置卡片 -->
<Border Grid.Row="3" Background="White" CornerRadius="6" Padding="12" Margin="0,5" Effect="{StaticResource CardShadow}">
<!-- 3. 样品体积 + 加压设置(合并到一行) -->
<Border Grid.Row="2" Background="White" CornerRadius="6" Padding="10" Margin="0,5" Effect="{StaticResource CardShadow}">
<WrapPanel>
<CheckBox IsChecked="{Binding UsePressure}" Content="使用加压测试 (附录A2)" VerticalAlignment="Center" Width="200" Margin="0,0,20,0"/>
<TextBlock Text="压力 (kPa):" VerticalAlignment="Center" Margin="0,0,8,0"/>
<TextBox Text="{Binding PressureValue}" Width="80" IsEnabled="{Binding UsePressure}" Margin="0,0,20,0"/>
<TextBlock Text="(当液体蒸气压 >33.8 kPa时必须加压" Foreground="#777777" VerticalAlignment="Center"/>
<TextBlock Text="样品体积 (mL):" VerticalAlignment="Center" Width="100"/>
<TextBox Text="{Binding SampleVolume}" Width="60" Margin="0,0,20,0"/>
<CheckBox IsChecked="{Binding UsePressure}" Content="加压测试" VerticalAlignment="Center" Margin="0,0,15,0"/>
<TextBlock Text="压力 (kPa):" VerticalAlignment="Center" Margin="0,0,5,0"/>
<TextBox Text="{Binding PressureValue}" Width="60" IsEnabled="{Binding UsePressure}" Margin="0,0,20,0"/>
<TextBlock Text="(蒸气压>33.8kPa时需加压)" Foreground="Gray" VerticalAlignment="Center"/>
</WrapPanel>
</Border>
<!-- 测量数据表格(卡片内嵌表格 -->
<Border Grid.Row="4" Background="White" CornerRadius="6" Padding="8" Margin="0,8" Effect="{StaticResource CardShadow}">
<!-- 4. 温升曲线图(核心新增 -->
<Border Grid.Row="3" Background="White" CornerRadius="6" Padding="8" Margin="0,5" Effect="{StaticResource CardShadow}">
<StackPanel>
<TextBlock Text="{Binding CurveTitle}" FontWeight="Bold" FontSize="13" Margin="0,0,0,5" Foreground="#1E4F7A"/>
<oxy:PlotView Model="{Binding TemperatureCurveModel}" Height="220"/>
</StackPanel>
</Border>
<!-- 5. 测量数据表格(占用剩余高度) -->
<Border Grid.Row="4" Background="White" CornerRadius="6" Padding="8" Margin="0,5" Effect="{StaticResource CardShadow}">
<DataGrid ItemsSource="{Binding Measurements}" AutoGenerateColumns="False"
CanUserAddRows="False" IsReadOnly="True"
HeadersVisibility="Column" GridLinesVisibility="Horizontal"
RowHeight="28" MinHeight="180">
RowHeight="28" MinHeight="150">
<DataGrid.Columns>
<DataGridTextColumn Header="序号" Binding="{Binding Index}" Width="60" IsReadOnly="True"/>
<DataGridTextColumn Header="热导率 (W/m·K)" Binding="{Binding ThermalConductivity, StringFormat=F5}" Width="*" IsReadOnly="True"/>
<DataGridTextColumn Header="热扩散率 (×10⁻⁶ m²/s)" Binding="{Binding ThermalDiffusivity, StringFormat=F5}" Width="*" IsReadOnly="True"/>
<DataGridTextColumn Header="体积热容 (kJ/m³·K)" Binding="{Binding VolumetricHeatCapacity, StringFormat=F2}" Width="*" IsReadOnly="True"/>
<DataGridTextColumn Header="序号" Binding="{Binding Index}" Width="60"/>
<DataGridTextColumn Header="热导率 (W/m·K)" Binding="{Binding ThermalConductivity, StringFormat=F5}" Width="*"/>
<DataGridTextColumn Header="热扩散率 (×10⁻⁶ m²/s)" Binding="{Binding ThermalDiffusivity, StringFormat=F5}" Width="*"/>
<DataGridTextColumn Header="体积热容 (kJ/m³·K)" Binding="{Binding VolumetricHeatCapacity, StringFormat=F2}" Width="*"/>
</DataGrid.Columns>
</DataGrid>
</Border>
<!-- 平均值显示卡片(高亮) -->
<Border Grid.Row="5" Background="#E8F0FE" CornerRadius="6" Padding="12" Margin="0,8" Effect="{StaticResource CardShadow}">
<!-- 6. 平均值 + 操作按钮 -->
<Border Grid.Row="5" Background="#E8F0FE" CornerRadius="6" Padding="10" Margin="0,5" Effect="{StaticResource CardShadow}">
<StackPanel>
<TextBlock Text="测量平均值" FontWeight="Bold" FontSize="14" Margin="0,0,0,8" Foreground="#1E4F7A"/>
<WrapPanel>
<WrapPanel Margin="0,0,0,8">
<TextBlock Text="平均热导率:" Width="100" FontWeight="SemiBold"/>
<TextBox Text="{Binding AverageThermalConductivity, StringFormat=F5}" Width="100" IsReadOnly="True" Background="White"/>
<TextBox Text="{Binding AverageThermalConductivity, StringFormat=F5}" Width="100" IsReadOnly="True"/>
<TextBlock Text="W/m·K" Margin="6,0,30,0"/>
<TextBlock Text="平均热扩散率:" Width="120" FontWeight="SemiBold"/>
<TextBox Text="{Binding AverageThermalDiffusivity, StringFormat=F5}" Width="100" IsReadOnly="True" Background="White"/>
<TextBox Text="{Binding AverageThermalDiffusivity, StringFormat=F5}" Width="100" IsReadOnly="True"/>
<TextBlock Text="×10⁻⁶ m²/s" Margin="6,0,30,0"/>
<TextBlock Text="平均体积热容:" Width="100" FontWeight="SemiBold"/>
<TextBox Text="{Binding AverageVolumetricHeatCapacity, StringFormat=F2}" Width="100" IsReadOnly="True" Background="White"/>
<TextBox Text="{Binding AverageVolumetricHeatCapacity, StringFormat=F2}" Width="100" IsReadOnly="True"/>
<TextBlock Text="kJ/m³·K" Margin="6,0,0,0"/>
</WrapPanel>
</StackPanel>
</Border>
<!-- 系统校准卡片 -->
<Border Grid.Row="6" Background="White" CornerRadius="6" Padding="12" Margin="0,5" Effect="{StaticResource CardShadow}">
<StackPanel>
<TextBlock Text="系统校准 (附录A3)" FontWeight="Bold" FontSize="14" Margin="0,0,0,8" Foreground="#1E4F7A"/>
<WrapPanel VerticalAlignment="Center">
<TextBlock Text="参考液:" VerticalAlignment="Center"/>
<ComboBox ItemsSource="{Binding ReferenceLiquids}" SelectedItem="{Binding SelectedReferenceLiquid}" Width="110" Margin="8,0" Background="White"/>
<TextBlock Text="参考热导率 (W/m·K):" VerticalAlignment="Center" Margin="15,0,5,0"/>
<TextBox Text="{Binding ReferenceConductivity}" Width="80" Margin="0,0,15,0"/>
<Button Content="开始校准" Command="{Binding PerformSystemCalibrationCommand}" Width="100"
IsEnabled="{Binding IsCalibrating, Converter={StaticResource InverseBooleanConverter}}"/>
</WrapPanel>
<TextBlock Text="{Binding CalibrationStatus}" FontSize="11" Foreground="#0066CC" Margin="0,8,0,0"/>
<TextBlock Text="注使用已知热导率的参考液如蒸馏水0.606 W/m·K @25℃验证系统精度误差应在±2%以内。"
FontSize="10" Foreground="#666666" Margin="0,5,0,0"/>
</StackPanel>
</Border>
<!-- 操作按钮 -->
<StackPanel Grid.Row="7" Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,15,0,10">
<Button Content="▶ 开始测试" Command="{Binding StartTestCommand}" Width="130" Height="38" Margin="8"
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button Content="▶ 开始测试" Command="{Binding StartTestCommand}" Width="130" Height="36" Margin="8"
IsEnabled="{Binding IsTesting, Converter={StaticResource InverseBooleanConverter}}"
Background="{StaticResource PrimaryButtonBrush}"/>
<Button Content="⟳ 重置" Command="{Binding ResetCommand}" Width="100" Height="38" Margin="8"/>
<Button Content="📄 生成报告" Command="{Binding GenerateReportCommand}" Width="110" Height="38" Margin="8"/>
<Button Content="⟳ 重置" Command="{Binding ResetCommand}" Width="100" Height="36" Margin="8"/>
<Button Content="📄 生成报告" Command="{Binding GenerateReportCommand}" Width="110" Height="36" Margin="8"/>
</StackPanel>
</StackPanel>
</Border>
<!-- 7. 系统校准(可选,可收起到折叠区域,为节省空间放在底部) -->
<Border Grid.Row="6" Background="White" CornerRadius="6" Padding="8" Margin="0,5" Effect="{StaticResource CardShadow}">
<StackPanel>
<TextBlock Text="系统校准 (附录A3)" FontWeight="Bold" Margin="0,0,0,5"/>
<WrapPanel>
<TextBlock Text="参考液:" VerticalAlignment="Center"/>
<ComboBox ItemsSource="{Binding ReferenceLiquids}" SelectedItem="{Binding SelectedReferenceLiquid}" Width="100" Margin="5,0"/>
<TextBlock Text="参考热导率 (W/m·K):" VerticalAlignment="Center" Margin="10,0,5,0"/>
<TextBox Text="{Binding ReferenceConductivity}" Width="70" Margin="0,0,10,0"/>
<Button Content="开始校准" Command="{Binding PerformSystemCalibrationCommand}" Width="100"/>
</WrapPanel>
<TextBlock Text="{Binding CalibrationStatus}" FontSize="11" Foreground="Blue" Margin="0,5,0,0"/>
</StackPanel>
</Border>
</Grid>
</ScrollViewer>
</UserControl>