using Microsoft.Win32; using StationProbe; using System; using System.Collections.Generic; using System.IO; using System.Text.Encodings.Web; using System.Text.Json; using System.Text.Unicode; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; namespace TestViewer { /// /// Interaction logic for MainWindow.xaml /// public partial class MainWindow { private readonly Database? _db; private DateTime _startDate = new(2023, 1, 1); private DateTime _endDate = DateTime.Now; private int _pageIndex = -1; private int _pageCount; private string _partKey = string.Empty; private string _conclusionKey = string.Empty; public MainWindow() { InitializeComponent(); CreateStart.SelectedDate = _startDate; CreateStart.DisplayDate = _startDate; CreateEnd.SelectedDate = _endDate; CreateEnd.DisplayDate = _endDate; CreateStart.SelectedDateChanged += (_, _) => { _startDate = CreateStart.SelectedDate.Value.Date; }; CreateEnd.SelectedDateChanged += (_, _) => { _endDate = CreateEnd.SelectedDate.Value.Date.AddDays(1); }; Loading.LoadingChanged += OnLoadingChanged; var fileDialog = new OpenFileDialog { Title = "Open database file", Filter = "*.db|*.db" }; if (fileDialog.ShowDialog() == true) { _db = new Database(fileDialog.FileName); PageIndex.Text = $"{_pageIndex + 1}/{_pageCount}"; var batchTasks = _db.GetBatchTasks(); foreach (var task in batchTasks) { BatchTaskList.Items.Add(task); } BatchTaskList.SelectionChanged += OnBatchTaskSelectionChanged; ExamList.SelectionChanged += OnExamSelectionChanged; } else { Application.Current.Shutdown(0); } } private void OnLoadingChanged(object? sender, bool e) { if (e) { Dispatcher.Invoke(() => { LoadingMask.Visibility = Visibility.Visible; }); } else { Dispatcher.Invoke(() => { LoadingMask.Visibility = Visibility.Collapsed; }); } } private void OnBatchTaskSelectionChanged(object sender, SelectionChangedEventArgs e) { if (BatchTaskList.SelectedValue is BatchTask batchTask) { Loading.Run(() => { _pageIndex = 0; _pageCount = _db!.GetPageCount(batchTask.Id, _partKey, _conclusionKey,_startDate, _endDate); var exams = _db.GetExams(batchTask.Id, _pageIndex, _partKey, _conclusionKey, _startDate, _endDate); Dispatcher.Invoke(() => { foreach (var exam in exams) { ExamList.Items.Add(exam); } PageIndex.Text = $"{_pageIndex + 1}/{_pageCount}"; }); }); } } private void OnExamSelectionChanged(object sender, SelectionChangedEventArgs e) { ExamScrollView.ScrollToHome(); ExamContent.Children.Clear(); if (ExamList.SelectedValue is Exam exam) { Dictionary? reportContent; try { reportContent = JsonSerializer.Deserialize>(exam.Report); } catch { reportContent = null; } if (reportContent != null) { var partStackPanel = new StackPanel() { Margin = new Thickness(16), Orientation = Orientation.Horizontal }; partStackPanel.Children.Add(new TextBlock() { VerticalAlignment = VerticalAlignment.Center, Text = "部位: ", FontWeight = FontWeights.Bold, FontSize = 16, }); partStackPanel.Children.Add(new TextBlock() { VerticalAlignment = VerticalAlignment.Center, Text = $"{reportContent["Part"]}", FontSize = 16, }); ExamContent.Children.Add(partStackPanel); var deviceStackPanel = new StackPanel() { Margin = new Thickness(16), Orientation = Orientation.Horizontal }; deviceStackPanel.Children.Add(new TextBlock() { VerticalAlignment = VerticalAlignment.Center, Text = "设备: ", FontWeight = FontWeights.Bold, FontSize = 16, }); deviceStackPanel.Children.Add(new TextBlock() { VerticalAlignment = VerticalAlignment.Center, Text = $"{reportContent["Device"]}", FontSize = 16, }); ExamContent.Children.Add(deviceStackPanel); var conclusionStackPanel = new StackPanel() { Margin = new Thickness(16), Orientation = Orientation.Horizontal }; conclusionStackPanel.Children.Add(new TextBlock() { VerticalAlignment = VerticalAlignment.Center, Text = "结论: ", FontWeight = FontWeights.Bold, FontSize = 16, }); var conclusion = "无结论"; if (!string.IsNullOrEmpty(reportContent["Conclusion"])) { conclusion = reportContent["Conclusion"]; } conclusionStackPanel.Children.Add(new TextBlock() { VerticalAlignment = VerticalAlignment.Center, Text = conclusion, FontSize = 16, }); ExamContent.Children.Add(conclusionStackPanel); ExamContent.Children.Add(new Border() { Height = 1, Width = 2000, BorderBrush = Brushes.Gray, Background = Brushes.Gray }); ExamContent.Children.Add(new TextBlock() { Width = 2000, Margin = new Thickness(16, 16, 16, 8), Text = "超声所见:", FontSize = 16, FontWeight = FontWeights.Bold, }); ExamContent.Children.Add(new TextBlock() { Margin = new Thickness(16, 8, 16, 16), Text = reportContent["Summary"].Replace(@"\n", Environment.NewLine), FontSize = 16, TextWrapping = TextWrapping.Wrap, }); ExamContent.Children.Add(new TextBlock() { Width = 2000, Margin = new Thickness(16, 16, 16, 8), Text = "超声提示:", FontSize = 16, FontWeight = FontWeights.Bold, }); ExamContent.Children.Add(new TextBlock() { Margin = new Thickness(16, 8, 16, 16), Text = reportContent["Comment"].Replace(@"\n", Environment.NewLine), FontSize = 16, TextWrapping = TextWrapping.Wrap, }); } else { ExamContent.Children.Add(new TextBlock() { Margin = new Thickness(16), Text = exam.Report, FontSize = 20, TextWrapping = TextWrapping.Wrap, }); } ExamContent.Children.Add(new Border() { Height = 1, Width = 2000, BorderBrush = Brushes.Gray, Background = Brushes.Gray }); var images = _db!.GetImages(exam.Id); foreach (var image in images) { var img = new BitmapImage(); img.BeginInit(); img.StreamSource = new MemoryStream(image.Data); img.EndInit(); var imageBorder = new Border { Margin = new Thickness(16), Width = 200, Height = 200, Background = Brushes.Black, Child = new System.Windows.Controls.Image() { Source = img }, Cursor = Cursors.Hand }; imageBorder.MouseDown += (_, _) => { var viewImageWindow = new Window { Owner = this, Background = Brushes.Black, WindowStartupLocation = WindowStartupLocation.CenterOwner }; var width = img.Width + 16; var height = img.Height + 16; if (width >= SystemParameters.PrimaryScreenWidth || height >= SystemParameters.PrimaryScreenHeight) { viewImageWindow.WindowState = WindowState.Maximized; } else { viewImageWindow.Width = width; viewImageWindow.Height = height; } viewImageWindow.Content = new System.Windows.Controls.Image() { Source = img }; viewImageWindow.ShowDialog(); }; ExamContent.Children.Add(imageBorder); } } } private void OnNextPageClick(object sender, RoutedEventArgs e) { if (_pageIndex < _pageCount - 1) { if (BatchTaskList.SelectedValue is BatchTask batchTask) { ExamList.Items.Clear(); _pageIndex++; Loading.Run(() => { var exams = _db!.GetExams(batchTask.Id, _pageIndex, _partKey, _conclusionKey,_startDate, _endDate); Dispatcher.Invoke(() => { foreach (var exam in exams) { ExamList.Items.Add(exam); } PageIndex.Text = $"{_pageIndex + 1}/{_pageCount}"; }); }); } } } private void OnPreviousPageClick(object sender, RoutedEventArgs e) { if (_pageIndex > 0) { if (BatchTaskList.SelectedValue is BatchTask batchTask) { ExamList.Items.Clear(); _pageIndex--; Loading.Run(() => { var exams = _db!.GetExams(batchTask.Id, _pageIndex, _partKey, _conclusionKey, _startDate, _endDate); Dispatcher.Invoke(() => { foreach (var exam in exams) { ExamList.Items.Add(exam); } PageIndex.Text = $"{_pageIndex + 1}/{_pageCount}"; }); }); } } } private void OnSearchClick(object sender, RoutedEventArgs e) { _partKey = PartKey.Text; _conclusionKey = ConclusionKey.Text; if (BatchTaskList.SelectedValue is BatchTask batchTask) { ExamList.Items.Clear(); Exam[]? exams; Loading.Run(() => { _pageCount = _db!.GetPageCount(batchTask.Id, _partKey, _conclusionKey, _startDate, _endDate); _pageIndex = 0; exams = _db.GetExams(batchTask.Id, _pageIndex, _partKey, _conclusionKey,_startDate, _endDate); Dispatcher.Invoke(() => { foreach (var exam in exams) { ExamList.Items.Add(exam); } PageIndex.Text = $"{_pageIndex + 1}/{_pageCount}"; }); }); } } private void OnExportClick(object sender, RoutedEventArgs e) { var partKey = PartKey.Text; var conclusionKey = ConclusionKey.Text; if (BatchTaskList.SelectedValue is BatchTask batchTask) { FolderBrowserEx.FolderBrowserDialog dialog = new FolderBrowserEx.FolderBrowserDialog(); var result = dialog.ShowDialog(); if (result == System.Windows.Forms.DialogResult.OK) { var targetFolder = dialog.SelectedFolder; var imageFolder = Path.Combine(targetFolder, "images"); if (!Directory.Exists(imageFolder)) { Directory.CreateDirectory(imageFolder); } var reportFolder = Path.Combine(targetFolder, "reports"); if (!Directory.Exists(reportFolder)) { Directory.CreateDirectory(reportFolder); } var progressWindow = new Window { Title = "导出中...", WindowStartupLocation = WindowStartupLocation.CenterOwner, WindowStyle = WindowStyle.ToolWindow, ResizeMode = ResizeMode.NoResize, Width = 320, Height = 80, Owner = this }; var canClose = false; progressWindow.Closing += (_, arg) => { arg.Cancel = !canClose; }; var progressBar = new ProgressBar { Minimum = 0, Maximum = 100, Value = 0 }; progressWindow.Content = progressBar; Task.Run(() => { JsonSerializerOptions opts = new JsonSerializerOptions { WriteIndented = true, Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) }; var pageCount = _db!.GetPageCount(batchTask.Id, partKey, conclusionKey,_startDate, _endDate); if (pageCount > 0) { for (int i = 0; i < pageCount; i++) { var exams = _db.GetExams(batchTask.Id, i, partKey, conclusionKey,_startDate, _endDate); foreach (var exam in exams) { var images = _db.GetImages(exam.Id); foreach (var image in images) { var fileName = Path.Combine(imageFolder, $"{exam.Id}_{image.Id}.jpg"); File.WriteAllBytes(fileName, image.Data); } var reportDic = new Dictionary { { "PatientName", exam.PatientName }, { "PatientSex", exam.PatientSex }, { "PatientAge", exam.PatientAge }, { "ExamDate", exam.ExamDate } }; Dictionary? reportContent; try { reportContent = JsonSerializer.Deserialize>(exam.Report); } catch { reportContent = null; } if (reportContent != null) { reportDic.Add("Report", reportContent); } else { reportDic.Add("Report", exam.Report); } var reportFile = Path.Combine(reportFolder, $"{exam.Id}.txt"); File.WriteAllText(reportFile, JsonSerializer.Serialize(reportDic, opts)); } var progress = (i + 1) / (double)pageCount * 100; Dispatcher.Invoke(() => { progressWindow.Title = $"导出中...{(int)progress}%"; progressBar.Value = progress; }); } canClose = true; Dispatcher.Invoke(progressWindow.Close); } }); progressWindow.ShowDialog(); } } } } }