using PdfSharpCore.Drawing; using PdfSharpCore.Pdf; using PdfSharpCore.Utils; using System; using System.Collections.ObjectModel; using System.ComponentModel; using System.Globalization; using System.IO; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Media; namespace EmptyLoadTest { // 数据模型 public class ReportItem { public int Index { get; set; } public DateTime Time { get; set; } public double Torque { get; set; } public int Speed { get; set; } public double Pressure { get; set; } public string Status { get; set; } public string Notes { get; set; } } // 状态到颜色的转换器 public class StatusToColorConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is string status) { return status switch { //"正常" => new SolidColorBrush(Color.FromRgb(39, 174, 96)), // 绿色 //"警告" => new SolidColorBrush(Color.FromRgb(230, 126, 34)), // 橙色 //"错误" => new SolidColorBrush(Color.FromRgb(231, 76, 60)), // 红色 _ => new SolidColorBrush(Color.FromRgb(52, 73, 94)) // 默认深蓝色 }; } return new SolidColorBrush(Color.FromRgb(52, 73, 94)); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } // 视图模型 public class ReportViewModel : INotifyPropertyChanged { private ObservableCollection _reportData; public ObservableCollection ReportData { get => _reportData; set { _reportData = value; OnPropertyChanged(nameof(ReportData)); UpdateStatistics(); } } private int _dataCount; public int DataCount { get => _dataCount; set { _dataCount = value; OnPropertyChanged(nameof(DataCount)); } } private int _normalCount; public int NormalCount { get => _normalCount; set { _normalCount = value; OnPropertyChanged(nameof(NormalCount)); } } private int _warningCount; public int WarningCount { get => _warningCount; set { _warningCount = value; OnPropertyChanged(nameof(WarningCount)); } } private int _errorCount; public int ErrorCount { get => _errorCount; set { _errorCount = value; OnPropertyChanged(nameof(ErrorCount)); } } public ReportViewModel(ObservableCollection realData = null) { if (realData != null && realData.Count > 0) { // 使用传入的真实数据 ReportData = realData; } UpdateStatistics(); } private void UpdateStatistics() { if (ReportData == null) return; DataCount = ReportData.Count; //NormalCount = ReportData.Count(item => item.Status == "正常"); //WarningCount = ReportData.Count(item => item.Status == "警告"); //ErrorCount = ReportData.Count(item => item.Status == "错误"); } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } // 在 ReportViewModel 类中添加这个方法 public void ExportData() { try { var saveDialog = new Microsoft.Win32.SaveFileDialog { Filter = "CSV文件|*.csv", FileName = $"过程报表_{DateTime.Now:yyyyMMdd_HHmmss}.csv", Title = "导出报表" }; if (saveDialog.ShowDialog() == true) { using (var writer = new StreamWriter(saveDialog.FileName, false, System.Text.Encoding.UTF8)) { writer.WriteLine("序号,时间,实时扭矩(N.cm),实时转速(Rad/Min)"); foreach (var item in ReportData) { writer.WriteLine($"{item.Index},{item.Time:HH:mm:ss},{item.Torque:F1},{item.Speed}"); } } MessageBox.Show($"报表已导出到:{saveDialog.FileName}", "导出成功"); } } catch (Exception ex) { MessageBox.Show($"导出失败:{ex.Message}", "错误"); } } public void Clear() { ReportData = new ObservableCollection(); } public void ExportToPdfUsingPdfSharp() { try { var saveDialog = new Microsoft.Win32.SaveFileDialog { Filter = "PDF文件|*.pdf", FileName = $"过程报表_{DateTime.Now:yyyyMMdd_HHmmss}.pdf" }; if (saveDialog.ShowDialog() == true) { // 创建PDF文档 PdfDocument document = new PdfDocument(); document.Info.Title = "医用刨削器过程测试报表"; document.Info.Author = "测试系统"; document.Info.CreationDate = DateTime.Now; // 添加页面 PdfPage page = document.AddPage(); XGraphics gfx = XGraphics.FromPdfPage(page); // 直接使用系统中文字体名称(Windows系统) // 常见的系统中文字体: // "Microsoft YaHei" - 微软雅黑 (Windows 7+) // "SimSun" - 宋体 // "SimHei" - 黑体 // "KaiTi" - 楷体 string fontName = "Microsoft YaHei"; // 使用微软雅黑 XFont titleFont = new XFont(fontName, 20, PdfSharpCore.Drawing.XFontStyle.Bold); XFont headerFont = new XFont(fontName, 12, PdfSharpCore.Drawing.XFontStyle.Bold); XFont normalFont = new XFont(fontName, 10, PdfSharpCore.Drawing.XFontStyle.Regular); // 页面尺寸 double pageWidth = page.Width; double margin = 50; double yPos = margin; // 1. 标题 gfx.DrawString("医用刨削器过程测试报表", titleFont, XBrushes.Black, new XRect(0, yPos, pageWidth, 30), XStringFormats.TopCenter); yPos += 40; // 2. 生成时间 gfx.DrawString($"生成时间:{DateTime.Now:yyyy年MM月dd日 HH:mm:ss}", headerFont, XBrushes.Black, new XRect(0, yPos, pageWidth, 20), XStringFormats.TopCenter); yPos += 30; // 3. 统计信息 string stats = $"数据总数:{DataCount} | 正常:{NormalCount} | 警告:{WarningCount} | 错误:{ErrorCount}"; gfx.DrawString(stats, headerFont, XBrushes.DarkBlue, new XRect(margin, yPos, pageWidth - 2 * margin, 20), XStringFormats.TopLeft); yPos += 30; // 4. 表格标题 gfx.DrawString("测试过程数据明细", headerFont, XBrushes.Black, new XRect(margin, yPos, pageWidth - 2 * margin, 20), XStringFormats.TopLeft); yPos += 25; // 5. 绘制表格 double columnWidth = (pageWidth - 2 * margin) / 4; double rowHeight = 20; // 表头 gfx.DrawString("序号", headerFont, XBrushes.Black, margin, yPos); gfx.DrawString("时间", headerFont, XBrushes.Black, margin + columnWidth, yPos); gfx.DrawString("扭矩(N.cm)", headerFont, XBrushes.Black, margin + columnWidth * 2, yPos); gfx.DrawString("转速(rad/min)", headerFont, XBrushes.Black, margin + columnWidth * 3, yPos); yPos += rowHeight; // 数据行 int rowCount = 0; foreach (var item in ReportData) { // 检查是否需要换页 if (yPos + rowHeight > page.Height - margin && rowCount > 0) { // 添加新页面 page = document.AddPage(); gfx = XGraphics.FromPdfPage(page); yPos = margin; // 在新页面绘制表头 gfx.DrawString("序号", headerFont, XBrushes.Black, margin, yPos); gfx.DrawString("时间", headerFont, XBrushes.Black, margin + columnWidth, yPos); gfx.DrawString("扭矩(N.cm)", headerFont, XBrushes.Black, margin + columnWidth * 2, yPos); gfx.DrawString("转速(rad/min)", headerFont, XBrushes.Black, margin + columnWidth * 3, yPos); yPos += rowHeight; } gfx.DrawString(item.Index.ToString(), normalFont, XBrushes.Black, margin, yPos); gfx.DrawString(item.Time.ToString("HH:mm:ss"), normalFont, XBrushes.Black, margin + columnWidth, yPos); gfx.DrawString(item.Torque.ToString("F1"), normalFont, XBrushes.Black, margin + columnWidth * 2, yPos); gfx.DrawString(item.Speed.ToString(), normalFont, XBrushes.Black, margin + columnWidth * 3, yPos); yPos += rowHeight; rowCount++; } // 保存PDF document.Save(saveDialog.FileName); MessageBox.Show($"PDF已导出到:{saveDialog.FileName}", "导出成功"); } } catch (Exception ex) { MessageBox.Show($"PDF导出失败:{ex.Message}", "错误"); } } } // 在窗口的代码后台设置DataContext public partial class ProcessReportWindow : Window { public ProcessReportWindow() { InitializeComponent(); var emergencyWindow = EmergencyStopWindow.Instance; var realData = emergencyWindow?.GetReportData(); if (realData != null && realData.Count > 0) { // 使用真实数据 DataContext = new ReportViewModel(realData); var masx = realData.Select(s => s.Torque).ToList(); var lasttime_ = realData.Max(s => s.Time); if (realData.Count > 0) { maxForce.Text = masx.Max().ToString("F3"); lasttime.Text = "最后刷新:" + lasttime_.ToString("yyyy-MM-dd HH:mm:ss"); } } else { // 如果没有真实数据,使用示例数据 DataContext = new ReportViewModel(); } } // 3. 修正单例逻辑:确保单例的 ReportData 可被外部修改,不丢失数据 private static ProcessReportWindow _instance; // 加锁保证线程安全 private static readonly object _lock = new object(); public static ProcessReportWindow Instance { get { lock (_lock) { if (_instance == null || !_instance.IsLoaded) { _instance = new ProcessReportWindow(); // 使用无参构造,初始化空数据 } return _instance; } } } private void Button_Click(object sender, RoutedEventArgs e) { var mainWindow = EmergencyStopWindow.Instance; if (!mainWindow.IsVisible) { mainWindow.Show(); } else { mainWindow.Activate(); } Close(); } private void Button_Click_1(object sender, RoutedEventArgs e) { if (DataContext is ReportViewModel viewModel) { viewModel.ExportData(); } } private void Button_Click_2(object sender, RoutedEventArgs e) { if (DataContext is ReportViewModel viewModel) { viewModel.ExportToPdfUsingPdfSharp(); } } private void Button_Click_3(object sender, RoutedEventArgs e) { var mainWindow = MainWindow.Instance; if (!mainWindow.IsVisible) { mainWindow.Show(); } else { mainWindow.Activate(); } Close(); } private void Button_Click_4(object sender, RoutedEventArgs e) { if (DataContext is ReportViewModel viewModel) { var emergencyWindow = EmergencyStopWindow.Instance; emergencyWindow?.ClearReportData(); viewModel.Clear(); } } private void Window_Loaded(object sender, RoutedEventArgs e) { if (DataContext is ReportViewModel viewModel) { viewModel.ExportData(); } } } }