using System; using System.Linq; using System.Windows; using System.Windows.Controls; using TabletTester2025.Models; namespace TabletTester2025 { public partial class SettingsWindow : Window { public SettingsWindow() { InitializeComponent(); LoadSettings(); } 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); } 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); p.HardnessTestCount = int.Parse(HardnessCountBox.Text); p.FriabilityTargetRpm = double.Parse(FriabilityRpmBox.Text); p.FriabilityTargetTimeMin = double.Parse(FriabilityTimeBox.Text); p.FriabilityTargetRounds = CalculateFriabilityRounds(p.FriabilityTargetTimeMin, p.FriabilityTargetRpm); p.FriabilityMaxLossPercent = double.Parse(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.Dissolution1TimeMin = int.Parse(Dissolution1TimeBox.Text); p.Dissolution2TimeMin = int.Parse(Dissolution2TimeBox.Text); p.Dissolution1SampleIntervalMin = double.Parse(Dissolution1IntervalBox.Text); p.Dissolution2SampleIntervalMin = double.Parse(Dissolution2IntervalBox.Text); p.DissolutionSampleTimes = SampleTimesBox.Text .Split(',', StringSplitOptions.RemoveEmptyEntries) .Select(s => int.Parse(s.Trim())) .ToArray(); ValidateParameters(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 (int.TryParse(FriabilityTimeBox?.Text, out int timeMin) && int.TryParse(FriabilityRpmBox?.Text, out int 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 (p.HardnessMin_N < 0 || p.HardnessMax_N <= p.HardnessMin_N) throw new InvalidOperationException("硬度内控上限必须大于下限。"); if (p.HardnessTestCount <= 0) throw new InvalidOperationException("硬度测试次数必须大于0。"); if (p.FriabilityTargetRpm <= 0 || p.FriabilityTargetTimeMin <= 0 || p.FriabilityTargetRounds <= 0 || p.FriabilityMaxLossPercent <= 0) throw new InvalidOperationException("脆碎度参数必须大于0。"); if (p.DisintegrationMaxSeconds <= 0 || p.DisintegrationSpeedRpm <= 0 || p.DisintegrationTemperatureC <= 0) throw new InvalidOperationException("崩解参数必须大于0。"); 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 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)); } } }