Files
PetroleumViscosityTest/MainWindow.xaml.cs
2026-02-12 17:03:23 +08:00

314 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Microsoft.VisualBasic;
using PetroleumViscosityTest.Controls;
using PetroleumViscosityTest.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
namespace PetroleumViscosityTest
{
public partial class MainWindow : Window
{
private ViscosityTestData currentData;
private List<double> rawTimes = new List<double>();
public MainWindow()
{
InitializeComponent();
currentData = new ViscosityTestData();
dpTestDate.SelectedDate = DateTime.Today;
UpdateThermostatTime();
}
// 温度变化时自动更新恒温时间表2
private void TxtTestTemp_TextChanged(object sender, TextChangedEventArgs e)
{
UpdateThermostatTime();
}
private void UpdateThermostatTime()
{
if (double.TryParse(txtTestTemp.Text, out double temp))
{
int time = Models.Constants.GetThermostatTime(temp);
txtThermostatTime.Text = time.ToString();
}
else
{
txtThermostatTime.Text = "";
}
}
// 加载示例数据
private void BtnLoadExample_Click(object sender, RoutedEventArgs e)
{
txtSampleID.Text = "S2026-001";
txtSampleName.Text = "润滑油";
txtTestTemp.Text = "50";
txtConstant.Text = "0.4780";
txtDensity.Text = "0.85";
txtOperator.Text = "张三";
txtRemark.Text = "示例数据";
txtTime1.Text = "322.4";
txtTime2.Text = "322.6";
txtTime3.Text = "321.0";
txtTime4.Text = "";
txtTime5.Text = "";
txtTime6.Text = "";
UpdateThermostatTime();
txtStatus.Text = "示例数据已加载";
}
// 清空所有输入
private void BtnClearAll_Click(object sender, RoutedEventArgs e)
{
txtSampleID.Clear();
txtSampleName.Clear();
txtTestTemp.Clear();
txtConstant.Clear();
txtDensity.Clear();
txtOperator.Clear();
txtRemark.Clear();
txtTime1.Clear();
txtTime2.Clear();
txtTime3.Clear();
txtTime4.Clear();
txtTime5.Clear();
txtTime6.Clear();
txtAvgTime.Clear();
txtViscosity.Clear();
txtDynamicViscosity.Clear();
txtValidCount.Clear();
txtPrecisionJudge.Clear();
txtRepeatability.Clear();
txtReproducibility.Clear();
txtMeasuredRepeatability.Clear();
txtRepeatJudge.Clear();
lstRawTimes.ItemsSource = null;
rawTimes.Clear();
txtStatus.Text = "已清空";
}
// 清空流动时间
private void BtnClearTimes_Click(object sender, RoutedEventArgs e)
{
txtTime1.Clear();
txtTime2.Clear();
txtTime3.Clear();
txtTime4.Clear();
txtTime5.Clear();
txtTime6.Clear();
rawTimes.Clear();
lstRawTimes.ItemsSource = null;
}
// 增加一次测量在界面中添加更多输入框为简化我们已预留6个
private void BtnAddMeasurement_Click(object sender, RoutedEventArgs e)
{
// 本版本固定6个输入框无需动态增加
MessageBox.Show("已支持最多6次测量请直接在对应框中输入。", "提示");
}
// 核心计算:运动粘度、动力粘度、精密度
private void BtnCalcViscosity_Click(object sender, RoutedEventArgs e)
{
try
{
// 1. 读取流动时间
rawTimes = GetTimeValues();
if (rawTimes.Count < 4)
{
MessageBox.Show("至少需要输入4次流动时间", "数据不足", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
// 2. 读取常数、密度、温度
if (!double.TryParse(txtConstant.Text, out double constant))
{
MessageBox.Show("请输入有效的粘度计常数 C", "参数错误", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
if (!double.TryParse(txtTestTemp.Text, out double temp))
{
MessageBox.Show("请输入试验温度", "参数错误", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
double density = 0;
if (!string.IsNullOrWhiteSpace(txtDensity.Text))
{
if (!double.TryParse(txtDensity.Text, out density))
{
MessageBox.Show("密度格式错误,将不计算动力粘度", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
// 3. 根据温度获取允许偏差(%
double allowedDeviationPercent = Models.Constants.GetAllowedDeviation(temp);
double allowedDeviation = 0;
// 4. 计算平均值、筛选有效数据
List<double> validTimes = new List<double>();
double avg = rawTimes.Average();
bool continueCalc = true;
int maxIterations = 10; // 防止死循环
while (continueCalc && maxIterations-- > 0)
{
validTimes = rawTimes.Where(t => Math.Abs(t - avg) <= avg * allowedDeviationPercent / 100.0).ToList();
if (validTimes.Count >= 3)
{
double newAvg = validTimes.Average();
if (Math.Abs(newAvg - avg) < 0.0001)
continueCalc = false;
else
avg = newAvg;
}
else
{
break;
}
}
if (validTimes.Count < 3)
{
MessageBox.Show("有效测量次数不足3次无法计算请检查数据是否离散过大。", "精密度超差", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
double finalAvg = validTimes.Average();
// 5. 计算运动粘度
double viscosity = constant * finalAvg;
// 6. 计算动力粘度(如果有密度)
double dynamicViscosity = 0;
if (density > 0)
{
dynamicViscosity = viscosity * density;
}
// 7. 计算本次测量的重复性(相对极差)
double measuredRepeatability = 0;
if (validTimes.Count > 1)
{
measuredRepeatability = (validTimes.Max() - validTimes.Min()) / finalAvg * 100;
}
// 8. 获取标准重复性限
double stdRepeatability = Models.Constants.GetRepeatabilityLimit(temp);
// 9. 更新UI
txtAvgTime.Text = finalAvg.ToString("F3");
txtViscosity.Text = viscosity.ToString("G4"); // 四位有效数字
if (density > 0)
txtDynamicViscosity.Text = dynamicViscosity.ToString("G4");
else
txtDynamicViscosity.Text = "未计算";
txtValidCount.Text = $"{validTimes.Count} / {rawTimes.Count}";
txtMeasuredRepeatability.Text = measuredRepeatability.ToString("F2") + "%";
txtRepeatability.Text = stdRepeatability.ToString("F1") + "%";
txtReproducibility.Text = Models.Constants.GetReproducibilityLimit(temp).ToString("F1") + "%";
bool repeatOK = measuredRepeatability <= stdRepeatability;
txtRepeatJudge.Text = repeatOK ? "合格" : $"超差 (允许 ≤ {stdRepeatability:F1}%)";
txtRepeatJudge.Foreground = repeatOK ? System.Windows.Media.Brushes.Green : System.Windows.Media.Brushes.Red;
txtPrecisionJudge.Text = repeatOK ? "精密度符合要求" : "精密度不符合要求,建议重新测试";
// 10. 显示原始数据
lstRawTimes.ItemsSource = rawTimes.Select((t, i) => new { Display = $"第{i + 1}次: {t:F3}s" }).ToList();
// 11. 保存当前数据到模型
currentData.SampleID = txtSampleID.Text;
currentData.SampleName = txtSampleName.Text;
currentData.TestTemp = temp;
currentData.Constant = constant;
currentData.Density = density > 0 ? density : (double?)null;
currentData.RawTimes = rawTimes;
currentData.ValidTimes = validTimes;
currentData.AvgTime = finalAvg;
currentData.Viscosity = viscosity;
currentData.DynamicViscosity = dynamicViscosity;
currentData.Operator = txtOperator.Text;
currentData.TestDate = dpTestDate.SelectedDate ?? DateTime.Now;
currentData.Remark = txtRemark.Text;
currentData.Repeatability = measuredRepeatability;
currentData.IsRepeatabilityOK = repeatOK;
txtStatus.Text = $"计算完成,有效次数 {validTimes.Count},运动粘度 {viscosity:G4} mm²/s";
}
catch (Exception ex)
{
MessageBox.Show($"计算错误: {ex.Message}", "异常", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
// 从文本框获取流动时间列表
private List<double> GetTimeValues()
{
var list = new List<double>();
AddIfValid(txtTime1, list);
AddIfValid(txtTime2, list);
AddIfValid(txtTime3, list);
AddIfValid(txtTime4, list);
AddIfValid(txtTime5, list);
AddIfValid(txtTime6, list);
return list;
}
private void AddIfValid(TextBox tb, List<double> list)
{
if (!string.IsNullOrWhiteSpace(tb.Text) && double.TryParse(tb.Text, out double val))
{
list.Add(val);
}
}
// 生成原始记录
private void BtnGenRecord_Click(object sender, RoutedEventArgs e)
{
if (currentData.Viscosity <= 0)
{
MessageBox.Show("请先计算运动粘度!", "无数据", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
var record = new TestRecordControl();
record.LoadData(currentData);
ReportContent.Content = record;
}
// 生成测试报告
private void BtnGenReport_Click(object sender, RoutedEventArgs e)
{
if (currentData.Viscosity <= 0)
{
MessageBox.Show("请先计算运动粘度!", "无数据", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
var report = new TestReportControl();
report.LoadData(currentData);
ReportContent.Content = report;
}
// 打印预览
private void BtnPrintPreview_Click(object sender, RoutedEventArgs e)
{
if (ReportContent.Content == null)
{
MessageBox.Show("请先生成记录或报告", "无报表", MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
if (ReportContent.Content is FrameworkElement visual)
{
PrintDialog printDialog = new PrintDialog();
if (printDialog.ShowDialog() == true)
{
printDialog.PrintVisual(visual, "粘度测试报表");
}
}
}
}
}