Files
MobilePhoneGrippingCuttingT…/ProcessReportWindow.xaml.cs

411 lines
14 KiB
C#
Raw Permalink Normal View History

2026-04-20 11:51:33 +08:00

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<ReportItem> _reportData;
public ObservableCollection<ReportItem> 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<ReportItem> 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<ReportItem>();
}
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();
}
}
}
}