#include "reportgenerator.h" #include #include #include ReportGenerator::ReportGenerator() { } void ReportGenerator::setData(const SpectrumReportData &data) { m_data = data; } QString ReportGenerator::formatScientific(double value, int precision) const { if (value == 0.0) { return QString("0.0000E+00"); } // 格式化为科学计数法,类似 2.7056E-01 QString result = QString::number(value, 'E', precision); // 确保指数部分有两位 QStringList parts = result.split('E'); if (parts.size() == 2) { QString mantissa = parts[0]; QString exponent = parts[1]; // 处理指数符号和位数 QChar sign = exponent[0]; QString num = exponent.mid(1); bool ok; int expNum = num.toInt(&ok); if (ok) { exponent = QString("%1%2").arg(sign).arg(QString::number(expNum).rightJustified(2, '0')); } result = QString("%1E%2").arg(mantissa).arg(exponent); } return result; } QString ReportGenerator::formatDecimal(double value, int precision) const { return QString::number(value, 'f', precision); } QString ReportGenerator::formatDateTime(const QDateTime &dt) const { return dt.toString("yyyy/M/d hh:mm:ss"); } QString ReportGenerator::generateHtmlHeader() const { return R"( 符合能谱分析报告 )"; } QString ReportGenerator::generateMeasurementSection() const { QString html; html += QString("
能谱文件:%1
") .arg(m_data.measurement.spectrumFile); html += "
测量参数
"; html += ""; html += QString("" "") .arg(formatDateTime(m_data.measurement.startTime)) .arg(formatDecimal(m_data.measurement.liveTime, 0)); html += QString("" "") .arg(formatDecimal(m_data.measurement.realTime, 0)) .arg(formatDecimal(m_data.measurement.deadTime, 2)); html += "
开始时间:%1活时间(S):%2
实时间(S):%1死时间:%2 %
"; return html; } QString ReportGenerator::generateCalibrationSection() const { QString html; html += "
刻度
"; html += ""; html += QString("" "") .arg(m_data.calibration.fileName) .arg(m_data.calibration.standardSource); html += "
文件:%1刻度标准源:%2
"; // 能量刻度 html += "
"; html += "
能量刻度
"; html += ""; html += QString("" "") .arg(formatDateTime(m_data.calibration.energy.generateTime)) .arg(formatDecimal(m_data.calibration.energy.intercept, 3)); html += QString("" "") .arg(formatDecimal(m_data.calibration.energy.slope, 3)) .arg(formatScientific(m_data.calibration.energy.quadratic, 3)); html += "
生成时间:%1截距:%2 keV
斜率:%1 keV/ch二次项系数:%2 keV/(ch^2)
"; html += "
"; // 效率刻度 html += "
"; html += "
效率刻度
"; html += ""; html += QString("" "") .arg(formatDateTime(m_data.calibration.efficiency.generateTime)) .arg(formatDecimal(m_data.calibration.efficiency.inflectionEnergy, 2)); html += QString("" "") .arg(m_data.calibration.efficiency.aboveInflection) .arg(formatDecimal(m_data.calibration.efficiency.aboveError, 2)); html += QString("" "") .arg(m_data.calibration.efficiency.belowInflection) .arg(formatDecimal(m_data.calibration.efficiency.belowError, 2)); html += QString("") .arg(m_data.calibration.efficiency.logEquation); html += "
生成时间:%1拐点能量(keV):%2
拐点以上:%1误差:%2%
拐点以下:%1误差:%2%
效率对数方程式:%1
"; html += "
"; return html; } QString ReportGenerator::generateNuclideLibSection() const { QString html; html += "
核素库
"; html += ""; html += QString("" "") .arg(m_data.nuclideLib.fileName) .arg(formatDecimal(m_data.nuclideLib.peakMatchWidth, 3)); html += "
文件:%1峰匹配宽度(keV):%2 * FWHM
"; return html; } QString ReportGenerator::generateAnalysisSection() const { QString html; html += "
分析参数
"; html += ""; html += QString("" "") .arg(formatDecimal(m_data.analysis.startEnergy, 2)) .arg(formatDecimal(m_data.analysis.endEnergy, 2)); html += QString("" "") .arg(formatDecimal(m_data.analysis.statErrorLimit, 3)) .arg(formatScientific(m_data.analysis.activityRatio, 4)); html += QString("") .arg(m_data.analysis.mdaMethod); html += "
起始能量(keV):%1终止能量(keV):%2
统计误差限值:%1%活度比例系数:%2
探测限计算方法:%1
"; return html; } QString ReportGenerator::generatePeakTableSection() const { QString html; html += "
能 谱 峰 一 览 表
"; html += ""; // 表头 - 第一行 html += ""; html += ""; html += ""; html += ""; html += ""; html += ""; html += ""; // 表头 - 第二行 html += ""; html += ""; // 峰子项1 html += ""; // 峰子项2 html += ""; // 峰子项3 html += ""; // 峰子项4 html += ""; // 数据行(8列,与表头对应) for (const auto& peak : m_data.peaks) { html += ""; html += QString("").arg(peak.nuclide); html += QString("").arg(formatScientific(peak.avgActivity, 4)); html += QString("").arg(formatDecimal(peak.avgUncertainty, 2)); html += QString("").arg(formatDecimal(peak.energy, 2)); html += QString("").arg(formatScientific(peak.peakActivity, 3)); html += QString("").arg(formatDecimal(peak.peakUncertainty, 2)); html += QString("").arg(formatScientific(peak.mda, 3)); html += QString("").arg(peak.remark); html += ""; } html += "
核素平均活度(贝克Bq)不确定度备注
能量keV活度(贝克Bq)不确定度最小可探测活度(MDA)(贝克Bq)
%1%1%1%%1%1%1%%1%1
"; // 峰提示码说明 html += "
"; html += "
峰提示码说明:
"; html += "
G - γ射线
"; html += "
X - X射线
"; html += "
ec - 内转换电子
"; html += "
"; return html; } QString ReportGenerator::generateSignatureSection() const { QString html; html += "
"; html += QString("
分析员:%1
") .arg(m_data.signature.analyst); html += QString("
审查员:%1
") .arg(m_data.signature.reviewer); html += QString("
实验室:%1
") .arg(m_data.signature.laboratory); html += QString("
日 期:%1
") .arg(m_data.signature.reportDate.toString("yyyy年MM月dd日")); html += "
"; return html; } QString ReportGenerator::generateHtmlFooter() const { return "\n"; } QString ReportGenerator::generateHtmlReport() const { QString html; html += generateHtmlHeader(); html += "
符合能谱分析报告
"; html += generateMeasurementSection(); html += generateCalibrationSection(); html += generateNuclideLibSection(); html += generateAnalysisSection(); html += generatePeakTableSection(); html += generateSignatureSection(); html += generateHtmlFooter(); return html; } QString ReportGenerator::generateTextReport() const { QString text; QTextStream stream(&text); stream << QStringLiteral(u"符合能谱分析报告\n"); stream << "========================================\n\n"; stream << QStringLiteral(u"能谱文件: ") << m_data.measurement.spectrumFile << "\n\n"; stream << QStringLiteral(u"测量参数\n"); stream << "----------------------------------------\n"; stream << QStringLiteral(u" 开始时间: ") << formatDateTime(m_data.measurement.startTime) << "\n"; stream << QStringLiteral(u" 活时间: ") << formatDecimal(m_data.measurement.liveTime, 0) << "\n"; stream << QStringLiteral(u" 实时间: ") << formatDecimal(m_data.measurement.realTime, 0) << "\n"; stream << QStringLiteral(u" 死时间: ") << formatDecimal(m_data.measurement.deadTime, 2) << " %\n\n"; stream << QStringLiteral(u"刻度\n"); stream << "----------------------------------------\n"; stream << QStringLiteral(u" 文件: ") << m_data.calibration.fileName << "\n\n"; stream << QStringLiteral(u" 能量刻度\n"); stream << QStringLiteral(u" 生成时间: ") << formatDateTime(m_data.calibration.energy.generateTime) << "\n"; stream << QStringLiteral(u" 截距: ") << formatDecimal(m_data.calibration.energy.intercept, 3) << " keV\n"; stream << QStringLiteral(u" 斜率: ") << formatDecimal(m_data.calibration.energy.slope, 3) << " keV/ch\n"; stream << QStringLiteral(u" 二次项系数: ") << formatScientific(m_data.calibration.energy.quadratic, 3) << " keV/(ch^2)\n\n"; stream << QStringLiteral(u" 效率刻度\n"); stream << QStringLiteral(u" 生成时间: ") << formatDateTime(m_data.calibration.efficiency.generateTime) << "\n"; stream << QStringLiteral(u" 拐点能量: " )<< formatDecimal(m_data.calibration.efficiency.inflectionEnergy, 2) << " keV\n"; stream << QStringLiteral(u" 拐点以上: ") << m_data.calibration.efficiency.aboveInflection << QStringLiteral(u" 误差 = ") << formatDecimal(m_data.calibration.efficiency.aboveError, 2) << " %\n"; stream << QStringLiteral(u" 拐点以下: ") << m_data.calibration.efficiency.belowInflection << QStringLiteral(u" 误差 = ") << formatDecimal(m_data.calibration.efficiency.belowError, 2) << " %\n"; stream << QStringLiteral(u" 效率对数方程式: ") << m_data.calibration.efficiency.logEquation << "\n\n"; stream << QStringLiteral(u"核素库\n"); stream << "----------------------------------------\n"; stream << QStringLiteral(u" 文件名: ") << m_data.nuclideLib.fileName << "\n"; stream << QStringLiteral(u" 峰匹配宽度: ") << formatDecimal(m_data.nuclideLib.peakMatchWidth, 3) << " * FWHM (keV)\n\n"; stream << QStringLiteral(u"分析参数\n"); stream << QStringLiteral(u"----------------------------------------\n"); stream << QStringLiteral(u" 起始能量: " )<< formatDecimal(m_data.analysis.startEnergy, 2) << " keV\n"; stream << QStringLiteral(u" 终止能量: ") << formatDecimal(m_data.analysis.endEnergy, 2) << " keV\n"; stream << QStringLiteral(u" 统计误差限值: ") << formatDecimal(m_data.analysis.statErrorLimit, 3) << "%\n"; stream << QStringLiteral(u" 活度比例系数: ") << formatScientific(m_data.analysis.activityRatio, 4) << "\n"; stream << QStringLiteral(u" 探测限计算方法: " )<< m_data.analysis.mdaMethod << "\n\n"; stream << QStringLiteral(u"********************* 能 谱 峰 一 览 表 ******************\n\n"); stream << QString("%1 %2 %3 %4 %5 %6 %7\n") .arg("核素", -10) .arg("平均活度(Bq)", -15) .arg("能量(keV)", -12) .arg("峰活度(Bq)", -15) .arg("MDA(Bq)", -15) .arg("提示码", -8) .arg("备注", -6); stream << "------------------------------------------------------------------------\n"; for (const auto& peak : m_data.peaks) { stream << QString("%1 %2 %3 %4 %5 %6 %7\n") .arg(peak.nuclide, -10) .arg(formatScientific(peak.avgActivity, 4), -15) .arg(formatDecimal(peak.energy, 2), -12) .arg(formatScientific(peak.peakActivity, 3), -15) .arg(formatScientific(peak.mda, 3), -15) .arg(peak.peakCode, -8) .arg(peak.remark, -6); } stream << "\n\n"; stream << QStringLiteral(u"分析员: " )<< m_data.signature.analyst << "\n"; stream << QStringLiteral(u"审查员: " )<< m_data.signature.reviewer << "\n"; stream << QStringLiteral(u"实验室: " )<< m_data.signature.laboratory << "\n"; stream << QStringLiteral(u"日 期: ") << m_data.signature.reportDate.toString("yyyy年MM月dd日") << "\n"; return text; } bool ReportGenerator::saveToFile(const QString &filePath) const { QFile file(filePath); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { return false; } QTextStream out(&file); out.setCodec("UTF-8"); if (filePath.endsWith(".html", Qt::CaseInsensitive) || filePath.endsWith(".htm", Qt::CaseInsensitive)) { out << generateHtmlReport(); } else { out << generateTextReport(); } file.close(); return true; } QString ReportGenerator::generateWordReport() const { QString html; QTextStream stream(&html); stream << "\n"; stream << "\n"; stream << "\n"; stream << "符合能谱分析报告\n"; stream << "\n"; stream << "\n"; stream << "\n"; stream << "\n"; // 报告标题 stream << QStringLiteral(u"
符合能谱分析报告
\n"); // 能谱文件 stream << QStringLiteral(u"
能谱文件:%1
\n") .arg(m_data.measurement.spectrumFile); // 测量参数 stream << QStringLiteral(u"
测量参数
\n"); stream << "\n"; stream << QStringLiteral(u"\n") .arg(formatDateTime(m_data.measurement.startTime)) .arg(formatDecimal(m_data.measurement.liveTime, 0)); stream << QStringLiteral(u"\n") .arg(formatDecimal(m_data.measurement.realTime, 0)) .arg(formatDecimal(m_data.measurement.deadTime, 2)); stream << "
开始时间:%1活时间(S):%2
实时间(S):%1死时间:%2 %
\n"; // 刻度 stream << QStringLiteral(u"
刻度
\n"); stream << "\n"; stream << QStringLiteral(u"\n") .arg(m_data.calibration.fileName) .arg(m_data.calibration.standardSource); stream << "
文件:%1刻度标准源:%2
\n"; // 能量刻度 stream << "
\n"; stream << QStringLiteral(u"
能量刻度
\n"); stream << "\n"; stream << QStringLiteral(u"\n") .arg(formatDateTime(m_data.calibration.energy.generateTime)) .arg(formatDecimal(m_data.calibration.energy.intercept, 3)); stream << QStringLiteral(u"\n") .arg(formatDecimal(m_data.calibration.energy.slope, 3)) .arg(formatScientific(m_data.calibration.energy.quadratic, 3)); stream << "
生成时间:%1截距:%2 keV
斜率:%1 keV/ch二次项系数:%2 keV/(ch^2)
\n"; stream << "
\n"; // 效率刻度 stream << "
\n"; stream << QStringLiteral(u"
效率刻度
\n"); stream << "\n"; stream << QStringLiteral(u"\n") .arg(formatDateTime(m_data.calibration.efficiency.generateTime)) .arg(formatDecimal(m_data.calibration.efficiency.inflectionEnergy, 2)); stream << QStringLiteral(u"\n") .arg(m_data.calibration.efficiency.aboveInflection) .arg(formatDecimal(m_data.calibration.efficiency.aboveError, 2)); stream << QStringLiteral(u"\n") .arg(m_data.calibration.efficiency.belowInflection) .arg(formatDecimal(m_data.calibration.efficiency.belowError, 2)); stream << QStringLiteral(u"\n") .arg(m_data.calibration.efficiency.logEquation); stream << "
生成时间:%1拐点能量(keV):%2
拐点以上:%1误差:%2%
拐点以下:%1误差:%2%
效率对数方程式:%1
\n"; stream << "
\n"; // 核素库 stream << QStringLiteral(u"
核素库
\n"); stream << "\n"; stream << QStringLiteral(u"\n") .arg(m_data.nuclideLib.fileName) .arg(formatDecimal(m_data.nuclideLib.peakMatchWidth, 3)); stream << "
文件:%1峰匹配宽度(keV):%2 * FWHM
\n"; // 分析参数 stream << QStringLiteral(u"
分析参数
\n"); stream << "\n"; stream << QStringLiteral(u"\n") .arg(formatDecimal(m_data.analysis.startEnergy, 2)) .arg(formatDecimal(m_data.analysis.endEnergy, 2)); stream << QStringLiteral(u"\n") .arg(formatDecimal(m_data.analysis.statErrorLimit, 3)) .arg(formatScientific(m_data.analysis.activityRatio, 4)); stream << QStringLiteral(u"\n") .arg(m_data.analysis.mdaMethod); stream << "
起始能量(keV):%1终止能量(keV):%2
统计误差限值:%1%活度比例系数:%2
探测限计算方法:%1
\n"; // 能谱峰一览表 stream << QStringLiteral(u"
能 谱 峰 一 览 表
\n"); stream << QStringLiteral(u"\n"); stream << QStringLiteral(u"\n"); stream << QStringLiteral(u"\n"); stream << QStringLiteral(u"\n"); stream << QStringLiteral(u"\n"); stream << QStringLiteral(u"\n"); stream << QStringLiteral(u"\n"); stream << QStringLiteral(u"\n"); stream << QStringLiteral(u"\n"); stream << QStringLiteral(u"\n"); stream << QStringLiteral(u"\n"); stream << QStringLiteral(u"\n"); stream << QStringLiteral(u"\n"); stream << QStringLiteral(u"\n"); for (const auto& peak : m_data.peaks) { stream << QStringLiteral(u"\n"); stream << QStringLiteral(u"\n").arg(peak.nuclide); stream << QStringLiteral(u"\n").arg(formatScientific(peak.avgActivity, 4)); stream << QStringLiteral(u"\n").arg(formatDecimal(peak.avgUncertainty, 2)); stream << QStringLiteral(u"\n").arg(formatDecimal(peak.energy, 2)); stream << QStringLiteral(u"\n").arg(formatScientific(peak.peakActivity, 3)); stream << QStringLiteral(u"\n").arg(formatDecimal(peak.peakUncertainty, 2)); stream << QStringLiteral(u"\n").arg(formatScientific(peak.mda, 3)); stream << QStringLiteral(u"\n").arg(peak.remark); stream << QStringLiteral(u"\n"); } stream << QStringLiteral(u"
核素平均活度(贝克Bq)不确定度备注
能量keV活度(贝克Bq)不确定度最小可探测活度(MDA)(贝克Bq)
%1%1%1%%1%1%1%%1%1
\n"); // 峰提示码说明 stream << QStringLiteral(u"
\n"); stream << QStringLiteral(u"
峰提示码说明:
\n"); stream << QStringLiteral(u"
G - γ射线
\n"); stream << QStringLiteral(u"
X - X射线
\n"); stream << QStringLiteral(u"
ec - 内转换电子
\n"); stream << QStringLiteral(u"
\n"); // 签名 stream << "
\n"; stream << QStringLiteral(u"
分析员:%1
\n") .arg(m_data.signature.analyst); stream << QStringLiteral(u"
审查员:%1
\n") .arg(m_data.signature.reviewer); stream << QStringLiteral(u"
实验室:%1
\n") .arg(m_data.signature.laboratory); stream << QStringLiteral(u"
日 期:%1
\n") .arg(m_data.signature.reportDate.toString("yyyy年MM月dd日")); stream << "
\n"; stream << "\n"; stream << "\n"; return html; } bool ReportGenerator::saveToWordFile(const QString &filePath) const { QFile file(filePath); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { return false; } QTextStream out(&file); out.setCodec("UTF-8"); out << generateWordReport(); file.close(); return true; }