Files
zijiuqizonghejianyanyi/ReportWindow.xaml.cs
GukSang.Jin 4acf0c7d14 更新
2026-03-16 19:58:18 +08:00

300 lines
13 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Dapper;
using Modbus.Device;
using MySql.Data.MySqlClient;
using System;
using System.Collections.ObjectModel;
using System.Configuration;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using .Data;
namespace
{
public partial class ReportWindow : Window
{
private MainWindow _mainWindow;
private ReportWindow _reportWindow;
public ObservableCollection<TestRecord> _records;
// 添加静态集合来保持数据
private static ObservableCollection<TestRecord> _staticRecords = new ObservableCollection<TestRecord>();
private static readonly string ReportFilePath = System.IO.Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
"氧气自救器检验报表.csv");
Function ma;
private TcpClient _tcpClient => ModbusResourceManager.Instance.TcpClient;
private IModbusMaster _modbusMaster => ModbusResourceManager.Instance.ModbusMaster;
public ReportWindow()
{
InitializeComponent();
_records = new ObservableCollection<TestRecord>();
_records = _staticRecords;
dataGrid.ItemsSource = _records;
}
// 添加新记录
public void AddRecord(string time, string date, double flowRate, string duration, double flowRate2, string no)
{
var record = new TestRecord
{
Id = _records.Count + 1,
Time = time,
Date = date,
FlowRate = flowRate,
Duration = duration,
CreateTime = DateTime.Now,
FlowRate2 = flowRate2,
No = no
};
_records.Insert(0, record); // 新记录插入到最前面
SaveRecords(time, date, flowRate, duration, flowRate2, no);
}
// 保存记录到文件
private void SaveRecords(string time, string date, double flowRate, string duration, double flowRate2, string No)
{
try
{
using (var connection = new MySqlConnection(DatabaseConfig.ConnectionString))
{
connection.Open();
var sql = @"INSERT INTO test_records (Time, Date, FlowRate, Duration, CreateTime,FlowRate2,No,Type)
VALUES (@Time, @Date, @FlowRate, @Duration, @CreateTime,@FlowRate2,@No,0)";
var record = new TestRecord
{
Time = time,
Date = date,
FlowRate = flowRate,
Duration = duration,
CreateTime = DateTime.Now,
FlowRate2 = flowRate2,
No = No
};
connection.Execute(sql, record);
}
}
catch (Exception ex)
{
MessageBox.Show($"保存记录失败:{ex.Message}", "错误",
MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void BtnExport_Click(object sender, RoutedEventArgs e)
{
try
{
// 数据校验:无数据时给出友好提示
if (_records == null || _records.Count == 0)
{
MessageBox.Show("没有数据可导出", "提示",
MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
// 保存文件对话框:后缀改为.xls支持Excel直接打开
var saveDialog = new Microsoft.Win32.SaveFileDialog
{
FileName = $"氧气自救器_供养量检验报表_{DateTime.Now:yyyyMMdd_HHmmss}.xls",
Filter = "Excel文件 (*.xls)|*.xls|所有文件 (*.*)|*.*",
Title = "导出供氧量检验报表"
};
if (saveDialog.ShowDialog() == true)
{
// 构建HTML表格核心通过CSS定义居中、列宽、样式Excel可识别
var htmlBuilder = new System.Text.StringBuilder();
htmlBuilder.AppendLine("<html><body>");
// 表格整体样式:带边框、边框合并、统一字体(微软雅黑)
htmlBuilder.AppendLine("<table border='1' style='border-collapse:collapse; font-family:微软雅黑; font-size:11px;'>");
// 1. 表头行:居中+加粗+加宽列宽(重点优化长内容列)
htmlBuilder.AppendLine("<tr style='background-color:#f0f0f0;'>");
htmlBuilder.AppendLine("<th style='width:100px; text-align:center; font-weight:bold; padding:6px;'>编号</th>");
htmlBuilder.AppendLine("<th style='width:140px; text-align:center; font-weight:bold; padding:6px;'>日期</th>"); // 加宽
htmlBuilder.AppendLine("<th style='width:100px; text-align:center; font-weight:bold; padding:6px;'>时间</th>");
htmlBuilder.AppendLine("<th style='width:160px; text-align:center; font-weight:bold; padding:6px;'>定量供氧流量(L/min)</th>"); // 加宽(字段名较长)
htmlBuilder.AppendLine("<th style='width:160px; text-align:center; font-weight:bold; padding:6px;'>自动/手动补给供氧量(L/min)</th>");
htmlBuilder.AppendLine("<th style='width:90px; text-align:center; font-weight:bold; padding:6px;'>样品编号</th>");
htmlBuilder.AppendLine("<th style='width:140px; text-align:center; font-weight:bold; padding:6px;'>测试时长</th>"); // 加宽(支持时长格式)
htmlBuilder.AppendLine("<th style='width:160px; text-align:center; font-weight:bold; padding:6px;'>记录时间</th>"); // 加宽
htmlBuilder.AppendLine("</tr>");
// 2. 数据行:居中对齐+数值格式化供氧流量保留2位小数
foreach (var record in _records)
{
htmlBuilder.AppendLine("<tr>");
// 每个单元格强制居中,添加内边距避免拥挤
htmlBuilder.AppendLine($"<td style='text-align:center; padding:6px;'>{record.Id.ToString() ?? ""}</td>");
htmlBuilder.AppendLine($"<td style='text-align:center; padding:6px;'>{record.Date?.ToString() ?? ""}</td>");
htmlBuilder.AppendLine($"<td style='text-align:center; padding:6px;'>{record.Time?.ToString() ?? ""}</td>");
htmlBuilder.AppendLine($"<td style='text-align:center; padding:6px;'>{record.FlowRate:F2}</td>"); // 供氧流量2位小数匹配单位
htmlBuilder.AppendLine($"<td style='text-align:center; padding:6px;'>{record.FlowRate2:F2}</td>"); // 供氧流量2位小数匹配单位
htmlBuilder.AppendLine($"<td style='text-align:center; padding:6px;'>{record.No?.ToString() ?? ""}</td>"); // 样品编号
htmlBuilder.AppendLine($"<td style='text-align:center; padding:6px;'>{record.Duration?.ToString() ?? ""}</td>"); // 测试时长
htmlBuilder.AppendLine($"<td style='text-align:center; padding:6px;'>{record.CreateTime:yyyy/MM/dd HH:mm:ss}</td>"); // 记录时间
htmlBuilder.AppendLine("</tr>");
}
// 闭合HTML标签确保格式正确
htmlBuilder.AppendLine("</table></body></html>");
// 保存文件UTF-8编码彻底避免中文乱码
System.IO.File.WriteAllText(saveDialog.FileName, htmlBuilder.ToString(), Encoding.UTF8);
// 导出成功提示:明确告知用户格式已自动设置
MessageBox.Show(
$"报表已成功导出到:\n{saveDialog.FileName}\n\n",
"导出成功(格式已自动设置)",
MessageBoxButton.OK, MessageBoxImage.Information);
}
}
catch (Exception ex)
{
// 异常捕获:给出具体错误信息,便于排查
MessageBox.Show($"导出失败:{ex.Message}", "错误",
MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void BtnClear_Click(object sender, RoutedEventArgs e)
{
var result = MessageBox.Show("确定要清空所有记录吗?此操作不可恢复!",
"确认清空", MessageBoxButton.YesNo, MessageBoxImage.Warning);
if (result == MessageBoxResult.Yes)
{
_records.Clear();
MessageBox.Show("记录已清空", "提示",
MessageBoxButton.OK, MessageBoxImage.Information);
}
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
string plcIp = "192.168.1.10";
bool initSuccess = Data.ModbusResourceManager.Instance.Init(plcIp, 502);
if (!initSuccess)
{
MessageBox.Show("连接Modbus服务器失败", "错误");
this.Close();
return;
}
// 检查连接状态
if (_tcpClient == null || !_tcpClient.Connected)
{
MessageBox.Show("Modbus连接异常", "错误");
this.Close();
return;
}
ma = new Function(_modbusMaster);
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
// 停止ViewModel的定时器
if (DataContext is MainViewModel viewModel)
{
viewModel.StopTimer();
}
// 释放Modbus资源
ModbusResourceManager.Instance?.Dispose();
// 延后到当前窗口完成关闭后再统一关停,避免关闭重入。
AppShutdownCoordinator.RequestShutdown();
}
private void Window_Closed(object sender, EventArgs e)
{
// 由应用级关停统一处理其他窗口,避免关闭链路重入。
}
private void BtnPrint_Click(object sender, RoutedEventArgs e)
{
if (_records == null || _records.Count == 0)
{
MessageBox.Show("无数据,不可打印", "提示",
MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
ma.BtnClickFunctionForNew(Function.ButtonType., 15);
}
private bool TryReconnect()
{
try
{
string plcIp = "192.168.1.10";
bool initSuccess = Data.ModbusResourceManager.Instance.Init(plcIp, 502);
if (initSuccess)
{
ma = new Function(_modbusMaster);
return true;
}
}
catch (Exception ex)
{
//ShowErrorMsg($"重新连接失败:{ex.Message}");
}
return false;
}
private void SwitchWindow<T>(ref T windowInstance, Func<T> createFunc) where T : Window, new()
{
// 2. 检查资源是否可用(添加重连机制)
if (_tcpClient == null || !_tcpClient.Connected || _modbusMaster == null)
{
// 尝试重新连接
bool reconnectSuccess = TryReconnect();
if (!reconnectSuccess)
{
MessageBox.Show("TCP连接已断开请重新连接", "提示");
return;
}
}
// 3. 复用窗口实例:不存在则创建,存在则激活
if (windowInstance == null)
{
windowInstance = createFunc();
// 添加窗口关闭事件处理
windowInstance.Closed += (s, args) =>
{
WindowNavigationHelper.RestoreWindow(this);
};
}
else
{
WindowNavigationHelper.ShowWithoutWhiteFlash(this, windowInstance);
return;
}
WindowNavigationHelper.ShowWithoutWhiteFlash(this, windowInstance);
}
private void BtnClose_Click(object sender, RoutedEventArgs e)
{
SwitchWindow(ref _mainWindow, () => new MainWindow());
}
}
}