diff --git a/Views/SettingsWindow.xaml.cs b/Views/SettingsWindow.xaml.cs index 4032103..cf958a8 100644 --- a/Views/SettingsWindow.xaml.cs +++ b/Views/SettingsWindow.xaml.cs @@ -36,37 +36,41 @@ namespace TabletTester2025 Dissolution2TimeBox.Text = p.Dissolution2TimeMin.ToString(); Dissolution1IntervalBox.Text = p.Dissolution1SampleIntervalMin.ToString(); Dissolution2IntervalBox.Text = p.Dissolution2SampleIntervalMin.ToString(); - SampleTimesBox.Text = string.Join(",", p.DissolutionSampleTimes); + SampleTimesBox.Text = string.Join(",", p.DissolutionSampleTimes ?? Array.Empty()); } private void SaveButton_Click(object sender, RoutedEventArgs e) { try { - var p = App.CurrentPharmaParams; - p.HardnessMin_N = double.Parse(HardnessMinBox.Text); - p.HardnessMax_N = double.Parse(HardnessMaxBox.Text); + 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); - p.FriabilityTargetRpm = double.Parse(FriabilityRpmBox.Text); - p.FriabilityTargetTimeMin = double.Parse(FriabilityTimeBox.Text); + p.FriabilityTargetRpm = ParseFiniteDouble(FriabilityRpmBox.Text, "脆碎度转速"); + p.FriabilityTargetTimeMin = ParseFiniteDouble(FriabilityTimeBox.Text, "脆碎度试验时间"); p.FriabilityTargetRounds = CalculateFriabilityRounds(p.FriabilityTargetTimeMin, p.FriabilityTargetRpm); - p.FriabilityMaxLossPercent = double.Parse(FriabilityMaxLossBox.Text); + p.FriabilityMaxLossPercent = ParseFiniteDouble(FriabilityMaxLossBox.Text, "最大失重率"); p.DisintegrationDosageForm = GetSelectedDisintegrationDosageForm(); p.DisintegrationMaxSeconds = int.Parse(DisintegrationMaxSecBox.Text); - p.DisintegrationSpeedRpm = double.Parse(DisintegrationSpeedBox.Text); - p.DisintegrationTemperatureC = double.Parse(DisintegrationTempBox.Text); - p.DissolutionMinPercentAt30min = double.Parse(DissolutionMinPercentBox.Text); - p.DissolutionTemperatureC = double.Parse(DissolutionTempBox.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 = double.Parse(Dissolution1IntervalBox.Text); - p.Dissolution2SampleIntervalMin = double.Parse(Dissolution2IntervalBox.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); + App.CurrentPharmaParams = p; App.SaveCurrentPharmaParameters(); MessageBox.Show("参数已保存并立即生效", "提示", MessageBoxButton.OK, MessageBoxImage.Information); @@ -96,8 +100,10 @@ namespace TabletTester2025 if (FriabilityRoundsBox == null) return; - if (int.TryParse(FriabilityTimeBox?.Text, out int timeMin) - && int.TryParse(FriabilityRpmBox?.Text, out int rpm) + 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) { @@ -132,14 +138,23 @@ namespace TabletTester2025 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) @@ -150,6 +165,14 @@ namespace TabletTester2025 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}必须为有效数字。"); + + return value; + } + private static double ResolveFriabilityTargetTimeMin(PharmaParameters p) { if (p.FriabilityTargetTimeMin > 0) diff --git a/Views/ShowData.xaml b/Views/ShowData.xaml index 32a29d9..c57566e 100644 --- a/Views/ShowData.xaml +++ b/Views/ShowData.xaml @@ -126,9 +126,13 @@ - + + + + + diff --git a/Views/ShowData.xaml.cs b/Views/ShowData.xaml.cs index 61b7962..fbf669c 100644 --- a/Views/ShowData.xaml.cs +++ b/Views/ShowData.xaml.cs @@ -79,6 +79,17 @@ namespace 片剂四用仪.Views // 窗口关闭时的取消异常,正常退出循环 break; } + catch + { + try + { + await Task.Delay(1000, token); + } + catch (OperationCanceledException) + { + break; + } + } //await Task.Delay(1000, token); } @@ -141,6 +152,7 @@ namespace 片剂四用仪.Views new PlcParamMapping("txt_DisintegrationTime", 420, PlcParamType.Int), new PlcParamMapping("txt_DissolutionTime", 430, PlcParamType.Int), + new PlcParamMapping("txt_Dissolution2Time", 440, PlcParamType.Int), new PlcParamMapping("txt_Dissolution1SamplingInterval", 432, PlcParamType.Float), new PlcParamMapping("txt_Dissolution2SamplingInterval", 442, PlcParamType.Float), diff --git a/appsettings.json b/appsettings.json index c12dc85..4cbf562 100644 --- a/appsettings.json +++ b/appsettings.json @@ -60,7 +60,9 @@ "Dissolution2StopCoil": 33, "Dissolution2SampleAckCoil": 34, "Dissolution1Time": 430, - "Dissolution2Time": 440 + "Dissolution2Time": 440, + "Dissolution1SampleInterval": 432, + "Dissolution2SampleInterval": 442 }, "PharmaStandard": { "StandardVersion": "中国药典2025",