Files
CSI-Z420-Tablet-Multi-Funct…/Views/SettingsWindow.xaml.cs
2026-05-19 17:27:12 +08:00

240 lines
12 KiB
C#

using System;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using TabletTester2025.Models;
namespace TabletTester2025
{
public partial class SettingsWindow : Window
{
public SettingsWindow()
{
InitializeComponent();
LoadSettings();
Loaded += SettingsWindow_Loaded;
}
private async void SettingsWindow_Loaded(object sender, RoutedEventArgs e)
{
await LoadHardnessPressureAsync();
}
private void LoadSettings()
{
var p = App.CurrentPharmaParams;
HardnessMinBox.Text = p.HardnessMin_N.ToString();
HardnessMaxBox.Text = p.HardnessMax_N.ToString();
HardnessCountBox.Text = p.HardnessTestCount.ToString();
FriabilityRpmBox.Text = p.FriabilityTargetRpm.ToString();
FriabilityTimeBox.Text = ResolveFriabilityTargetTimeMin(p).ToString("0.###");
FriabilityRoundsBox.Text = CalculateFriabilityRounds(
ResolveFriabilityTargetTimeMin(p),
p.FriabilityTargetRpm > 0 ? p.FriabilityTargetRpm : 25).ToString();
FriabilityMaxLossBox.Text = p.FriabilityMaxLossPercent.ToString();
SelectDisintegrationDosageForm(p.DisintegrationDosageForm);
DisintegrationMaxSecBox.Text = p.DisintegrationMaxSeconds.ToString();
DisintegrationSpeedBox.Text = p.DisintegrationSpeedRpm.ToString();
DisintegrationTempBox.Text = p.DisintegrationTemperatureC.ToString();
DissolutionMinPercentBox.Text = p.DissolutionMinPercentAt30min.ToString();
DissolutionTempBox.Text = p.DissolutionTemperatureC.ToString();
Dissolution1TimeBox.Text = p.Dissolution1TimeMin.ToString();
Dissolution2TimeBox.Text = p.Dissolution2TimeMin.ToString();
Dissolution1IntervalBox.Text = p.Dissolution1SampleIntervalMin.ToString();
Dissolution2IntervalBox.Text = p.Dissolution2SampleIntervalMin.ToString();
SampleTimesBox.Text = string.Join(",", p.DissolutionSampleTimes ?? Array.Empty<int>());
}
private async void SaveButton_Click(object sender, RoutedEventArgs e)
{
try
{
var p = new PharmaParameters
{
StandardVersion = App.CurrentPharmaParams.StandardVersion
};
p.HardnessMin_N = ParseFiniteDouble(HardnessMinBox.Text, "硬度内控下限");
p.HardnessMax_N = ParseFiniteDouble(HardnessMaxBox.Text, "硬度内控上限");
p.HardnessTestCount = int.Parse(HardnessCountBox.Text);
double hardnessPressure = ParseFiniteDouble(HardnessPressureBox.Text, "加压压力");
p.FriabilityTargetRpm = ParseFiniteDouble(FriabilityRpmBox.Text, "脆碎度转速");
p.FriabilityTargetTimeMin = ParseFiniteDouble(FriabilityTimeBox.Text, "脆碎度试验时间");
p.FriabilityTargetRounds = CalculateFriabilityRounds(p.FriabilityTargetTimeMin, p.FriabilityTargetRpm);
p.FriabilityMaxLossPercent = ParseFiniteDouble(FriabilityMaxLossBox.Text, "最大失重率");
p.DisintegrationDosageForm = GetSelectedDisintegrationDosageForm();
p.DisintegrationMaxSeconds = int.Parse(DisintegrationMaxSecBox.Text);
p.DisintegrationSpeedRpm = ParseFiniteDouble(DisintegrationSpeedBox.Text, "崩解升降频率");
p.DisintegrationTemperatureC = ParseFiniteDouble(DisintegrationTempBox.Text, "崩解介质温度");
p.DissolutionMinPercentAt30min = ParseFiniteDouble(DissolutionMinPercentBox.Text, "30分钟最低溶出度");
p.DissolutionTemperatureC = ParseFiniteDouble(DissolutionTempBox.Text, "溶出介质温度");
p.Dissolution1TimeMin = int.Parse(Dissolution1TimeBox.Text);
p.Dissolution2TimeMin = int.Parse(Dissolution2TimeBox.Text);
p.Dissolution1SampleIntervalMin = ParseFiniteDouble(Dissolution1IntervalBox.Text, "溶出1取样间隔");
p.Dissolution2SampleIntervalMin = ParseFiniteDouble(Dissolution2IntervalBox.Text, "溶出2取样间隔");
p.DissolutionSampleTimes = SampleTimesBox.Text
.Split(',', StringSplitOptions.RemoveEmptyEntries)
.Select(s => int.Parse(s.Trim()))
.ToArray();
ValidateParameters(p);
await WriteHardnessPressureAsync(hardnessPressure);
App.CurrentPharmaParams = p;
App.SaveCurrentPharmaParameters();
MessageBox.Show("参数已保存并立即生效", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
DialogResult = true;
Close();
}
catch (Exception ex)
{
MessageBox.Show($"输入格式错误: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
DialogResult = false;
Close();
}
private void DisintegrationDosageFormBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (DisintegrationDosageFormBox.SelectedItem is ComboBoxItem item && item.Tag is string seconds)
DisintegrationMaxSecBox.Text = seconds;
}
private void FriabilityCalculationBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (FriabilityRoundsBox == null)
return;
if (double.TryParse(FriabilityTimeBox?.Text, out double timeMin)
&& double.IsFinite(timeMin)
&& double.TryParse(FriabilityRpmBox?.Text, out double rpm)
&& double.IsFinite(rpm)
&& timeMin > 0
&& rpm > 0)
{
FriabilityRoundsBox.Text = CalculateFriabilityRounds(timeMin, rpm).ToString();
}
else
{
FriabilityRoundsBox.Text = "";
}
}
private void SelectDisintegrationDosageForm(string dosageForm)
{
foreach (ComboBoxItem item in DisintegrationDosageFormBox.Items)
{
if (string.Equals(item.Content?.ToString(), dosageForm, StringComparison.OrdinalIgnoreCase))
{
DisintegrationDosageFormBox.SelectedItem = item;
return;
}
}
DisintegrationDosageFormBox.SelectedIndex = 0;
}
private string GetSelectedDisintegrationDosageForm()
{
return DisintegrationDosageFormBox.SelectedItem is ComboBoxItem item
? item.Content?.ToString() ?? "普通片"
: "普通片";
}
private static void ValidateParameters(PharmaParameters p)
{
if (!double.IsFinite(p.HardnessMin_N) || !double.IsFinite(p.HardnessMax_N))
throw new InvalidOperationException("硬度内控参数必须为有效数字。");
if (p.HardnessMin_N < 0 || p.HardnessMax_N <= p.HardnessMin_N)
throw new InvalidOperationException("硬度内控上限必须大于下限。");
if (p.HardnessTestCount <= 0)
throw new InvalidOperationException("硬度测试次数必须大于0。");
if (!double.IsFinite(p.FriabilityTargetRpm) || !double.IsFinite(p.FriabilityTargetTimeMin) || !double.IsFinite(p.FriabilityMaxLossPercent))
throw new InvalidOperationException("脆碎度参数必须为有效数字。");
if (p.FriabilityTargetRpm <= 0 || p.FriabilityTargetTimeMin <= 0 || p.FriabilityTargetRounds <= 0 || p.FriabilityMaxLossPercent <= 0)
throw new InvalidOperationException("脆碎度参数必须大于0。");
if (!double.IsFinite(p.DisintegrationSpeedRpm) || !double.IsFinite(p.DisintegrationTemperatureC))
throw new InvalidOperationException("崩解参数必须为有效数字。");
if (p.DisintegrationMaxSeconds <= 0 || p.DisintegrationSpeedRpm <= 0 || p.DisintegrationTemperatureC <= 0)
throw new InvalidOperationException("崩解参数必须大于0。");
if (!double.IsFinite(p.DissolutionMinPercentAt30min) || !double.IsFinite(p.DissolutionTemperatureC)
|| !double.IsFinite(p.Dissolution1SampleIntervalMin) || !double.IsFinite(p.Dissolution2SampleIntervalMin))
throw new InvalidOperationException("溶出度参数必须为有效数字。");
if (p.DissolutionMinPercentAt30min < 0 || p.DissolutionMinPercentAt30min > 150)
throw new InvalidOperationException("溶出度Q值应在0到150之间。");
if (p.DissolutionTemperatureC <= 0 || p.Dissolution1TimeMin <= 0 || p.Dissolution2TimeMin <= 0)
throw new InvalidOperationException("溶出温度和运行时间必须大于0。");
if (p.Dissolution1SampleIntervalMin <= 0 || p.Dissolution2SampleIntervalMin <= 0)
throw new InvalidOperationException("溶出取样间隔必须大于0。");
if (p.DissolutionSampleTimes == null || p.DissolutionSampleTimes.Length == 0 || p.DissolutionSampleTimes.Any(t => t <= 0))
throw new InvalidOperationException("溶出取样时间点必须为大于0的分钟数。");
}
private static double ParseFiniteDouble(string text, string fieldName)
{
if (!double.TryParse(text, out double value) || !double.IsFinite(value))
throw new InvalidOperationException($"{fieldName}必须为有效数字。");
if (value < 0)
throw new InvalidOperationException($"{fieldName}不能小于0。");
return value;
}
private async Task LoadHardnessPressureAsync()
{
ushort registerAddress = ResolveHardnessPressureRegister();
if (registerAddress == 0)
return;
try
{
float value = await App.PlcService.ReadFloatAsync(registerAddress);
if (float.IsFinite(value))
HardnessPressureBox.Text = value.ToString("0.###");
}
catch
{
HardnessPressureBox.Text = "";
}
}
private static async Task WriteHardnessPressureAsync(double value)
{
ushort registerAddress = ResolveHardnessPressureRegister();
if (registerAddress == 0)
throw new InvalidOperationException("加压压力PLC寄存器地址未配置。");
await App.PlcService.WriteFloatAsync(registerAddress, (float)value);
}
private static ushort ResolveHardnessPressureRegister()
{
return App.PlcConfig.HardnessPressure != 0 ? App.PlcConfig.HardnessPressure : (ushort)1480;
}
private static double ResolveFriabilityTargetTimeMin(PharmaParameters p)
{
if (p.FriabilityTargetTimeMin > 0)
return p.FriabilityTargetTimeMin;
double rpm = p.FriabilityTargetRpm > 0 ? p.FriabilityTargetRpm : 25;
if (p.FriabilityTargetRounds > 0 && rpm > 0)
return p.FriabilityTargetRounds / rpm;
return 4.0;
}
private static int CalculateFriabilityRounds(double timeMin, double rpm)
{
if (timeMin <= 0 || rpm <= 0)
return 0;
return Math.Max(1, (int)Math.Round(timeMin * rpm, MidpointRounding.AwayFromZero));
}
}
}