新增分析报告自动生成(可编辑存在问题),新增效率刻度界面(功能未实现)
This commit is contained in:
parent
eae91f1813
commit
9d1164e336
14
src/EfficiencyScale.cpp
Normal file
14
src/EfficiencyScale.cpp
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
#include "EfficiencyScale.h"
|
||||||
|
#include "ui_EfficiencyScale.h"
|
||||||
|
|
||||||
|
EfficiencyScale::EfficiencyScale(QWidget *parent)
|
||||||
|
: QDialog(parent)
|
||||||
|
, ui(new Ui::EfficiencyScale)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
EfficiencyScale::~EfficiencyScale()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
22
src/EfficiencyScale.h
Normal file
22
src/EfficiencyScale.h
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef EFFICIENCYSCALE_H
|
||||||
|
#define EFFICIENCYSCALE_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class EfficiencyScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
class EfficiencyScale : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit EfficiencyScale(QWidget *parent = nullptr);
|
||||||
|
~EfficiencyScale();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::EfficiencyScale *ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // EFFICIENCYSCALE_H
|
||||||
342
src/EfficiencyScale.ui
Normal file
342
src/EfficiencyScale.ui
Normal file
|
|
@ -0,0 +1,342 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>EfficiencyScale</class>
|
||||||
|
<widget class="QDialog" name="EfficiencyScale">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1173</width>
|
||||||
|
<height>709</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Dialog</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="2,7">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_3">
|
||||||
|
<property name="title">
|
||||||
|
<string>效率刻度管理列表</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="listWidget"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pBtn_Add_File">
|
||||||
|
<property name="text">
|
||||||
|
<string>添加</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pBtn_Delete_File">
|
||||||
|
<property name="text">
|
||||||
|
<string>删除</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_6" stretch="3,5">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,4">
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3" stretch="3,1,5,0,1,1">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_2">
|
||||||
|
<property name="title">
|
||||||
|
<string>效率刻度信息</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QGridLayout" name="gridLayout" columnstretch="2,3" rowminimumheight="2,3" columnminimumwidth="0,0">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>85</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>效率刻度命名:</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="lineEdit_name"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>85</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>备注说明:</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QPlainTextEdit" name="plainTextEdit_description">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pBtn_Save">
|
||||||
|
<property name="text">
|
||||||
|
<string>保存</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pBtn_SaveAs">
|
||||||
|
<property name="text">
|
||||||
|
<string>另存为</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>公式拟合</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>拟合公式:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="comboBox_fit_type">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pBtn_fitting">
|
||||||
|
<property name="text">
|
||||||
|
<string>拟合</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_fit_type_text">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>287</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>y = a + bx</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_fit_result">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>287</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>a = 1.21823, b = -5.0542</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>效率刻度拟合数据</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pBtn_Add">
|
||||||
|
<property name="text">
|
||||||
|
<string>新增</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pBtn_Delete">
|
||||||
|
<property name="text">
|
||||||
|
<string>删除</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="widget" native="true">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="layout_fittingCurve">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTableWidget" name="tablew_scale_data">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<attribute name="horizontalHeaderCascadingSectionResizes">
|
||||||
|
<bool>true</bool>
|
||||||
|
</attribute>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>序号</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>能量(key)</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>净计数率</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>探测效率</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>拟合效率</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>误差</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>刻度日期</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
|
|
@ -36,6 +36,7 @@
|
||||||
#include "EnergyScaleDataModel.h"
|
#include "EnergyScaleDataModel.h"
|
||||||
#include "EnergyCountPlotView.h"
|
#include "EnergyCountPlotView.h"
|
||||||
#include "ParticleCountPlotView.h"
|
#include "ParticleCountPlotView.h"
|
||||||
|
#include "reportwidget.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
#include "csv.h"
|
#include "csv.h"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
@ -869,3 +870,26 @@ void MainWindow::onParticleEnergyDataUpdated(const QString &energySpectrumFilena
|
||||||
// 更新数据表格
|
// 更新数据表格
|
||||||
// updataTable();
|
// updataTable();
|
||||||
}
|
}
|
||||||
|
void MainWindow::on_action_analysisReport_triggered()
|
||||||
|
{
|
||||||
|
ReportWidget *widget = new ReportWidget();
|
||||||
|
widget->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "EfficiencyScale.h"
|
||||||
|
void MainWindow::on_action_efficiency_scale_mrg_triggered()
|
||||||
|
{
|
||||||
|
// QDialog energy_scale_mrg_dlg;
|
||||||
|
// energy_scale_mrg_dlg.setObjectName("EfficiencyScaleFormDlg");
|
||||||
|
// energy_scale_mrg_dlg.setWindowTitle(QStringLiteral(u"效率刻度管理"));
|
||||||
|
// energy_scale_mrg_dlg.setWindowFlags(energy_scale_mrg_dlg.windowFlags() | Qt::WindowMaximizeButtonHint);
|
||||||
|
EfficiencyScale* efficiency_scale_mrg_form = new EfficiencyScale();
|
||||||
|
efficiency_scale_mrg_form->setWindowTitle(QStringLiteral(u"效率刻度管理"));
|
||||||
|
efficiency_scale_mrg_form->setWindowFlags(efficiency_scale_mrg_form->windowFlags() | Qt::WindowMaximizeButtonHint);
|
||||||
|
|
||||||
|
// QHBoxLayout* hlayout = new QHBoxLayout;
|
||||||
|
// hlayout->addWidget(efficiency_scale_mrg_form);
|
||||||
|
// efficiency_scale_mrg_form.setLayout(hlayout);
|
||||||
|
efficiency_scale_mrg_form->exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,10 @@ private slots:
|
||||||
void onMeasureStopped(bool success, const QString& message);
|
void onMeasureStopped(bool success, const QString& message);
|
||||||
|
|
||||||
void onDeviceStatusMessage(const QString& msg);
|
void onDeviceStatusMessage(const QString& msg);
|
||||||
|
void on_action_analysisReport_triggered();
|
||||||
|
|
||||||
|
void on_action_efficiency_scale_mrg_triggered();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMutex _mutex_info_output;
|
QMutex _mutex_info_output;
|
||||||
QPlainTextEdit* _plain_edit_info_output;
|
QPlainTextEdit* _plain_edit_info_output;
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1079</width>
|
<width>1079</width>
|
||||||
<height>22</height>
|
<height>21</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QMenu" name="menu_measurement_analysis">
|
<widget class="QMenu" name="menu_measurement_analysis">
|
||||||
|
|
@ -112,6 +112,7 @@
|
||||||
<addaction name="action_roi"/>
|
<addaction name="action_roi"/>
|
||||||
<addaction name="action_efficiency_scale_mrg"/>
|
<addaction name="action_efficiency_scale_mrg"/>
|
||||||
<addaction name="action_nuclideLib"/>
|
<addaction name="action_nuclideLib"/>
|
||||||
|
<addaction name="action_analysisReport"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QToolBar" name="toolBar">
|
<widget class="QToolBar" name="toolBar">
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
|
@ -230,6 +231,14 @@
|
||||||
<enum>QAction::TextHeuristicRole</enum>
|
<enum>QAction::TextHeuristicRole</enum>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="action_analysisReport">
|
||||||
|
<property name="text">
|
||||||
|
<string>分析报告自动生成</string>
|
||||||
|
</property>
|
||||||
|
<property name="menuRole">
|
||||||
|
<enum>QAction::NoRole</enum>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
|
|
||||||
|
|
@ -321,6 +321,8 @@ void NuclideAnalysisView::onActionPlotClear()
|
||||||
|
|
||||||
m_allFitResults.clear();
|
m_allFitResults.clear();
|
||||||
|
|
||||||
|
m_nuclideTable->setRowCount(0);
|
||||||
|
|
||||||
m_bSelecting = false;
|
m_bSelecting = false;
|
||||||
m_bSelectHS = false;
|
m_bSelectHS = false;
|
||||||
|
|
||||||
|
|
|
||||||
687
src/analysisReport/reportgenerator.cpp
Normal file
687
src/analysisReport/reportgenerator.cpp
Normal file
|
|
@ -0,0 +1,687 @@
|
||||||
|
#include "reportgenerator.h"
|
||||||
|
#include <QFile>
|
||||||
|
#include <QTextStream>
|
||||||
|
#include <QLocale>
|
||||||
|
|
||||||
|
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"(
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>符合能谱分析报告</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: "SimSun", "宋体", serif;
|
||||||
|
font-size: 12px;
|
||||||
|
margin: 20px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
.report-title {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.section-title {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-top: 15px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
border-bottom: 1px solid #333;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
table, th, td {
|
||||||
|
border: 1px solid #333;
|
||||||
|
}
|
||||||
|
th, td {
|
||||||
|
padding: 6px 8px;
|
||||||
|
text-align: left;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.param-table td:first-child {
|
||||||
|
width: 150px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.peak-table {
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
.peak-table th {
|
||||||
|
text-align: center;
|
||||||
|
background-color: #e8e8e8;
|
||||||
|
}
|
||||||
|
.peak-table td {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.signature-section {
|
||||||
|
margin-top: 30px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.signature-line {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
.spectrum-file-header {
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.legend {
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: 11px;
|
||||||
|
color: #555;
|
||||||
|
}
|
||||||
|
.legend-item {
|
||||||
|
margin-bottom: 3px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
)";
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ReportGenerator::generateMeasurementSection() const
|
||||||
|
{
|
||||||
|
QString html;
|
||||||
|
html += QString("<div class='spectrum-file-header'>能谱文件:%1</div>")
|
||||||
|
.arg(m_data.measurement.spectrumFile);
|
||||||
|
|
||||||
|
html += "<div class='section-title'>测量参数</div>";
|
||||||
|
html += "<table class='param-table'>";
|
||||||
|
html += QString("<tr><td>开始时间:</td><td>%1</td>"
|
||||||
|
"<td>活时间(S):</td><td>%2</td></tr>")
|
||||||
|
.arg(formatDateTime(m_data.measurement.startTime))
|
||||||
|
.arg(formatDecimal(m_data.measurement.liveTime, 0));
|
||||||
|
html += QString("<tr><td>实时间(S):</td><td>%1</td>"
|
||||||
|
"<td>死时间:</td><td>%2 %</td></tr>")
|
||||||
|
.arg(formatDecimal(m_data.measurement.realTime, 0))
|
||||||
|
.arg(formatDecimal(m_data.measurement.deadTime, 2));
|
||||||
|
html += "</table>";
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ReportGenerator::generateCalibrationSection() const
|
||||||
|
{
|
||||||
|
QString html;
|
||||||
|
html += "<div class='section-title'>刻度</div>";
|
||||||
|
html += "<table class='param-table'>";
|
||||||
|
html += QString("<tr><td>文件:</td><td>%1</td>"
|
||||||
|
"<td>刻度标准源:</td><td>%2</td></tr>")
|
||||||
|
.arg(m_data.calibration.fileName)
|
||||||
|
.arg(m_data.calibration.standardSource);
|
||||||
|
html += "</table>";
|
||||||
|
|
||||||
|
// 能量刻度
|
||||||
|
html += "<div style='margin-left: 20px; margin-top: 10px;'>";
|
||||||
|
html += "<div style='font-weight: bold;'>能量刻度</div>";
|
||||||
|
html += "<table class='param-table'>";
|
||||||
|
html += QString("<tr><td>生成时间:</td><td>%1</td>"
|
||||||
|
"<td>截距:</td><td>%2 keV</td></tr>")
|
||||||
|
.arg(formatDateTime(m_data.calibration.energy.generateTime))
|
||||||
|
.arg(formatDecimal(m_data.calibration.energy.intercept, 3));
|
||||||
|
html += QString("<tr><td>斜率:</td><td>%1 keV/ch</td>"
|
||||||
|
"<td>二次项系数:</td><td>%2 keV/(ch^2)</td></tr>")
|
||||||
|
.arg(formatDecimal(m_data.calibration.energy.slope, 3))
|
||||||
|
.arg(formatScientific(m_data.calibration.energy.quadratic, 3));
|
||||||
|
html += "</table>";
|
||||||
|
html += "</div>";
|
||||||
|
|
||||||
|
// 效率刻度
|
||||||
|
html += "<div style='margin-left: 20px; margin-top: 10px;'>";
|
||||||
|
html += "<div style='font-weight: bold;'>效率刻度</div>";
|
||||||
|
html += "<table class='param-table'>";
|
||||||
|
html += QString("<tr><td>生成时间:</td><td>%1</td>"
|
||||||
|
"<td>拐点能量(keV):</td><td>%2</td></tr>")
|
||||||
|
.arg(formatDateTime(m_data.calibration.efficiency.generateTime))
|
||||||
|
.arg(formatDecimal(m_data.calibration.efficiency.inflectionEnergy, 2));
|
||||||
|
html += QString("<tr><td>拐点以上:</td><td>%1</td>"
|
||||||
|
"<td>误差:</td><td>%2%</td></tr>")
|
||||||
|
.arg(m_data.calibration.efficiency.aboveInflection)
|
||||||
|
.arg(formatDecimal(m_data.calibration.efficiency.aboveError, 2));
|
||||||
|
html += QString("<tr><td>拐点以下:</td><td>%1</td>"
|
||||||
|
"<td>误差:</td><td>%2%</td></tr>")
|
||||||
|
.arg(m_data.calibration.efficiency.belowInflection)
|
||||||
|
.arg(formatDecimal(m_data.calibration.efficiency.belowError, 2));
|
||||||
|
html += QString("<tr><td>效率对数方程式:</td><td colspan='3'>%1</td></tr>")
|
||||||
|
.arg(m_data.calibration.efficiency.logEquation);
|
||||||
|
html += "</table>";
|
||||||
|
html += "</div>";
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ReportGenerator::generateNuclideLibSection() const
|
||||||
|
{
|
||||||
|
QString html;
|
||||||
|
html += "<div class='section-title'>核素库</div>";
|
||||||
|
html += "<table class='param-table'>";
|
||||||
|
html += QString("<tr><td>文件:</td><td>%1</td>"
|
||||||
|
"<td>峰匹配宽度(keV):</td><td>%2 * FWHM</td></tr>")
|
||||||
|
.arg(m_data.nuclideLib.fileName)
|
||||||
|
.arg(formatDecimal(m_data.nuclideLib.peakMatchWidth, 3));
|
||||||
|
html += "</table>";
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ReportGenerator::generateAnalysisSection() const
|
||||||
|
{
|
||||||
|
QString html;
|
||||||
|
html += "<div class='section-title'>分析参数</div>";
|
||||||
|
html += "<table class='param-table'>";
|
||||||
|
html += QString("<tr><td>起始能量(keV):</td><td>%1</td>"
|
||||||
|
"<td>终止能量(keV):</td><td>%2</td></tr>")
|
||||||
|
.arg(formatDecimal(m_data.analysis.startEnergy, 2))
|
||||||
|
.arg(formatDecimal(m_data.analysis.endEnergy, 2));
|
||||||
|
html += QString("<tr><td>统计误差限值:</td><td>%1%</td>"
|
||||||
|
"<td>活度比例系数:</td><td>%2</td></tr>")
|
||||||
|
.arg(formatDecimal(m_data.analysis.statErrorLimit, 3))
|
||||||
|
.arg(formatScientific(m_data.analysis.activityRatio, 4));
|
||||||
|
html += QString("<tr><td>探测限计算方法:</td><td colspan='3'>%1</td></tr>")
|
||||||
|
.arg(m_data.analysis.mdaMethod);
|
||||||
|
html += "</table>";
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ReportGenerator::generatePeakTableSection() const
|
||||||
|
{
|
||||||
|
QString html;
|
||||||
|
html += "<div class='section-title'>能 谱 峰 一 览 表</div>";
|
||||||
|
html += "<table class='peak-table'>";
|
||||||
|
|
||||||
|
// 表头 - 第一行
|
||||||
|
html += "<tr>";
|
||||||
|
html += "<th rowspan='2'>核素</th>";
|
||||||
|
html += "<th rowspan='2'>平均活度(贝克Bq)</th>";
|
||||||
|
html += "<th rowspan='2'>不确定度</th>";
|
||||||
|
html += "<th colspan='4'>峰</th>";
|
||||||
|
html += "<th rowspan='2'>备注</th>";
|
||||||
|
html += "</tr>";
|
||||||
|
|
||||||
|
// 表头 - 第二行
|
||||||
|
html += "<tr>";
|
||||||
|
html += "<th>能量keV</th>"; // 峰子项1
|
||||||
|
html += "<th>活度(贝克Bq)</th>"; // 峰子项2
|
||||||
|
html += "<th>不确定度</th>"; // 峰子项3
|
||||||
|
html += "<th>最小可探测活度(MDA)(贝克Bq)</th>"; // 峰子项4
|
||||||
|
html += "</tr>";
|
||||||
|
|
||||||
|
// 数据行(8列,与表头对应)
|
||||||
|
for (const auto& peak : m_data.peaks) {
|
||||||
|
html += "<tr>";
|
||||||
|
html += QString("<td>%1</td>").arg(peak.nuclide);
|
||||||
|
html += QString("<td>%1</td>").arg(formatScientific(peak.avgActivity, 4));
|
||||||
|
html += QString("<td>%1%</td>").arg(formatDecimal(peak.avgUncertainty, 2));
|
||||||
|
html += QString("<td>%1</td>").arg(formatDecimal(peak.energy, 2));
|
||||||
|
html += QString("<td>%1</td>").arg(formatScientific(peak.peakActivity, 3));
|
||||||
|
html += QString("<td>%1%</td>").arg(formatDecimal(peak.peakUncertainty, 2));
|
||||||
|
html += QString("<td>%1</td>").arg(formatScientific(peak.mda, 3));
|
||||||
|
html += QString("<td>%1</td>").arg(peak.remark);
|
||||||
|
html += "</tr>";
|
||||||
|
}
|
||||||
|
|
||||||
|
html += "</table>";
|
||||||
|
|
||||||
|
// 峰提示码说明
|
||||||
|
html += "<div class='legend'>";
|
||||||
|
html += "<div style='font-weight: bold; margin-bottom: 5px;'>峰提示码说明:</div>";
|
||||||
|
html += "<div class='legend-item'>G - γ射线</div>";
|
||||||
|
html += "<div class='legend-item'>X - X射线</div>";
|
||||||
|
html += "<div class='legend-item'>ec - 内转换电子</div>";
|
||||||
|
html += "</div>";
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ReportGenerator::generateSignatureSection() const
|
||||||
|
{
|
||||||
|
QString html;
|
||||||
|
html += "<div class='signature-section'>";
|
||||||
|
html += QString("<div class='signature-line'>分析员:%1</div>")
|
||||||
|
.arg(m_data.signature.analyst);
|
||||||
|
html += QString("<div class='signature-line'>审查员:%1</div>")
|
||||||
|
.arg(m_data.signature.reviewer);
|
||||||
|
html += QString("<div class='signature-line'>实验室:%1</div>")
|
||||||
|
.arg(m_data.signature.laboratory);
|
||||||
|
html += QString("<div class='signature-line'>日 期:%1</div>")
|
||||||
|
.arg(m_data.signature.reportDate.toString("yyyy年MM月dd日"));
|
||||||
|
html += "</div>";
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ReportGenerator::generateHtmlFooter() const
|
||||||
|
{
|
||||||
|
return "</body>\n</html>";
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ReportGenerator::generateHtmlReport() const
|
||||||
|
{
|
||||||
|
QString html;
|
||||||
|
html += generateHtmlHeader();
|
||||||
|
html += "<div class='report-title'>符合能谱分析报告</div>";
|
||||||
|
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 << "<html xmlns:o='urn:schemas-microsoft-com:office:office'\n";
|
||||||
|
stream << " xmlns:w='urn:schemas-microsoft-com:office:word'\n";
|
||||||
|
stream << " xmlns='http://www.w3.org/TR/REC-html40'>\n";
|
||||||
|
stream << "<head>\n";
|
||||||
|
stream << "<meta charset='UTF-8'>\n";
|
||||||
|
stream << "<title>符合能谱分析报告</title>\n";
|
||||||
|
stream << "<!--[if gte mso 9]>\n";
|
||||||
|
stream << "<xml>\n";
|
||||||
|
stream << "<w:WordDocument>\n";
|
||||||
|
stream << "<w:View>Print</w:View>\n";
|
||||||
|
stream << "<w:Zoom>100</w:Zoom>\n";
|
||||||
|
stream << "<w:DoNotOptimizeForBrowser/>\n";
|
||||||
|
stream << "</w:WordDocument>\n";
|
||||||
|
stream << "</xml>\n";
|
||||||
|
stream << "<![endif]-->\n";
|
||||||
|
stream << "<style>\n";
|
||||||
|
stream << " body {\n";
|
||||||
|
stream << " font-family: 'SimSun', '宋体', serif;\n";
|
||||||
|
stream << " font-size: 12pt;\n";
|
||||||
|
stream << " line-height: 1.5;\n";
|
||||||
|
stream << " margin: 2.54cm 3.17cm;\n";
|
||||||
|
stream << " }\n";
|
||||||
|
stream << " .report-title {\n";
|
||||||
|
stream << " text-align: center;\n";
|
||||||
|
stream << " font-size: 18pt;\n";
|
||||||
|
stream << " font-weight: bold;\n";
|
||||||
|
stream << " margin-bottom: 20pt;\n";
|
||||||
|
stream << " }\n";
|
||||||
|
stream << " .section-title {\n";
|
||||||
|
stream << " font-weight: bold;\n";
|
||||||
|
stream << " font-size: 14pt;\n";
|
||||||
|
stream << " margin-top: 15pt;\n";
|
||||||
|
stream << " margin-left: 0pt;\n";
|
||||||
|
stream << " margin-bottom: 8pt;\n";
|
||||||
|
stream << " border-bottom: 1px solid #000;\n";
|
||||||
|
stream << " padding-bottom: 3pt;\n";
|
||||||
|
stream << " }\n";
|
||||||
|
stream << " table {\n";
|
||||||
|
stream << " width: 100%;\n";
|
||||||
|
stream << " border-collapse: collapse;\n";
|
||||||
|
stream << " margin-bottom: 8pt;\n";
|
||||||
|
stream << " font-size: 11pt;\n";
|
||||||
|
stream << " }\n";
|
||||||
|
stream << " table, th, td {\n";
|
||||||
|
stream << " border: 1px solid #000;\n";
|
||||||
|
stream << " }\n";
|
||||||
|
stream << " th, td {\n";
|
||||||
|
stream << " padding: 5pt 8pt;\n";
|
||||||
|
stream << " text-align: left;\n";
|
||||||
|
stream << " }\n";
|
||||||
|
stream << " th {\n";
|
||||||
|
stream << " background-color: #f0f0f0;\n";
|
||||||
|
stream << " font-weight: bold;\n";
|
||||||
|
stream << " text-align: center;\n";
|
||||||
|
stream << " }\n";
|
||||||
|
stream << " .param-table td:first-child {\n";
|
||||||
|
stream << " width: 140pt;\n";
|
||||||
|
stream << " font-weight: bold;\n";
|
||||||
|
stream << " }\n";
|
||||||
|
stream << " .peak-table {\n";
|
||||||
|
stream << " font-size: 10pt;\n";
|
||||||
|
stream << " }\n";
|
||||||
|
stream << " .peak-table td {\n";
|
||||||
|
stream << " text-align: center;\n";
|
||||||
|
stream << " }\n";
|
||||||
|
stream << " .signature-section {\n";
|
||||||
|
stream << " margin-top: 30pt;\n";
|
||||||
|
stream << " text-align: right;\n";
|
||||||
|
stream << " font-size: 12pt;\n";
|
||||||
|
stream << " }\n";
|
||||||
|
stream << " .signature-line {\n";
|
||||||
|
stream << " margin-bottom: 8pt;\n";
|
||||||
|
stream << " }\n";
|
||||||
|
stream << " .spectrum-file-header {\n";
|
||||||
|
stream << " text-align: center;\n";
|
||||||
|
stream << " font-weight: bold;\n";
|
||||||
|
stream << " font-size: 13pt;\n";
|
||||||
|
stream << " margin-bottom: 10pt;\n";
|
||||||
|
stream << " }\n";
|
||||||
|
stream << " .calibration-sub {\n";
|
||||||
|
stream << " margin-left: 20pt;\n";
|
||||||
|
stream << " margin-top: 8pt;\n";
|
||||||
|
stream << " }\n";
|
||||||
|
stream << " .calibration-sub-title {\n";
|
||||||
|
stream << " font-weight: bold;\n";
|
||||||
|
stream << " margin-bottom: 5pt;\n";
|
||||||
|
stream << " }\n";
|
||||||
|
stream << " .legend {\n";
|
||||||
|
stream << " margin-top: 8pt;\n";
|
||||||
|
stream << " font-size: 10pt;\n";
|
||||||
|
stream << " color: #333;\n";
|
||||||
|
stream << " }\n";
|
||||||
|
stream << " .legend-title {\n";
|
||||||
|
stream << " font-weight: bold;\n";
|
||||||
|
stream << " margin-bottom: 3pt;\n";
|
||||||
|
stream << " }\n";
|
||||||
|
stream << "</style>\n";
|
||||||
|
stream << "</head>\n";
|
||||||
|
stream << "<body>\n";
|
||||||
|
|
||||||
|
// 报告标题
|
||||||
|
stream << QStringLiteral(u"<div class='report-title'>符合能谱分析报告</div>\n");
|
||||||
|
|
||||||
|
// 能谱文件
|
||||||
|
stream << QStringLiteral(u"<div class='spectrum-file-header'>能谱文件:%1</div>\n")
|
||||||
|
.arg(m_data.measurement.spectrumFile);
|
||||||
|
|
||||||
|
// 测量参数
|
||||||
|
stream << QStringLiteral(u"<div class='section-title'>测量参数</div>\n");
|
||||||
|
stream << "<table class='param-table'>\n";
|
||||||
|
stream << QStringLiteral(u"<tr><td>开始时间:</td><td>%1</td><td>活时间(S):</td><td>%2</td></tr>\n")
|
||||||
|
.arg(formatDateTime(m_data.measurement.startTime))
|
||||||
|
.arg(formatDecimal(m_data.measurement.liveTime, 0));
|
||||||
|
stream << QStringLiteral(u"<tr><td>实时间(S):</td><td>%1</td><td>死时间:</td><td>%2 %</td></tr>\n")
|
||||||
|
.arg(formatDecimal(m_data.measurement.realTime, 0))
|
||||||
|
.arg(formatDecimal(m_data.measurement.deadTime, 2));
|
||||||
|
stream << "</table>\n";
|
||||||
|
|
||||||
|
// 刻度
|
||||||
|
stream << QStringLiteral(u"<div class='section-title'>刻度</div>\n");
|
||||||
|
stream << "<table class='param-table'>\n";
|
||||||
|
stream << QStringLiteral(u"<tr><td>文件:</td><td>%1</td><td>刻度标准源:</td><td>%2</td></tr>\n")
|
||||||
|
.arg(m_data.calibration.fileName)
|
||||||
|
.arg(m_data.calibration.standardSource);
|
||||||
|
stream << "</table>\n";
|
||||||
|
|
||||||
|
// 能量刻度
|
||||||
|
stream << "<div class='calibration-sub'>\n";
|
||||||
|
stream << QStringLiteral(u"<div class='calibration-sub-title'>能量刻度</div>\n");
|
||||||
|
stream << "<table class='param-table'>\n";
|
||||||
|
stream << QStringLiteral(u"<tr><td>生成时间:</td><td>%1</td><td>截距:</td><td>%2 keV</td></tr>\n")
|
||||||
|
.arg(formatDateTime(m_data.calibration.energy.generateTime))
|
||||||
|
.arg(formatDecimal(m_data.calibration.energy.intercept, 3));
|
||||||
|
stream << QStringLiteral(u"<tr><td>斜率:</td><td>%1 keV/ch</td><td>二次项系数:</td><td>%2 keV/(ch^2)</td></tr>\n")
|
||||||
|
.arg(formatDecimal(m_data.calibration.energy.slope, 3))
|
||||||
|
.arg(formatScientific(m_data.calibration.energy.quadratic, 3));
|
||||||
|
stream << "</table>\n";
|
||||||
|
stream << "</div>\n";
|
||||||
|
|
||||||
|
// 效率刻度
|
||||||
|
stream << "<div class='calibration-sub'>\n";
|
||||||
|
stream << QStringLiteral(u"<div class='calibration-sub-title'>效率刻度</div>\n");
|
||||||
|
stream << "<table class='param-table'>\n";
|
||||||
|
stream << QStringLiteral(u"<tr><td>生成时间:</td><td>%1</td><td>拐点能量(keV):</td><td>%2</td></tr>\n")
|
||||||
|
.arg(formatDateTime(m_data.calibration.efficiency.generateTime))
|
||||||
|
.arg(formatDecimal(m_data.calibration.efficiency.inflectionEnergy, 2));
|
||||||
|
stream << QStringLiteral(u"<tr><td>拐点以上:</td><td>%1</td><td>误差:</td><td>%2%</td></tr>\n")
|
||||||
|
.arg(m_data.calibration.efficiency.aboveInflection)
|
||||||
|
.arg(formatDecimal(m_data.calibration.efficiency.aboveError, 2));
|
||||||
|
stream << QStringLiteral(u"<tr><td>拐点以下:</td><td>%1</td><td>误差:</td><td>%2%</td></tr>\n")
|
||||||
|
.arg(m_data.calibration.efficiency.belowInflection)
|
||||||
|
.arg(formatDecimal(m_data.calibration.efficiency.belowError, 2));
|
||||||
|
stream << QStringLiteral(u"<tr><td>效率对数方程式:</td><td colspan='3'>%1</td></tr>\n")
|
||||||
|
.arg(m_data.calibration.efficiency.logEquation);
|
||||||
|
stream << "</table>\n";
|
||||||
|
stream << "</div>\n";
|
||||||
|
|
||||||
|
// 核素库
|
||||||
|
stream << QStringLiteral(u"<div class='section-title'>核素库</div>\n");
|
||||||
|
stream << "<table class='param-table'>\n";
|
||||||
|
stream << QStringLiteral(u"<tr><td>文件:</td><td>%1</td><td>峰匹配宽度(keV):</td><td>%2 * FWHM</td></tr>\n")
|
||||||
|
.arg(m_data.nuclideLib.fileName)
|
||||||
|
.arg(formatDecimal(m_data.nuclideLib.peakMatchWidth, 3));
|
||||||
|
stream << "</table>\n";
|
||||||
|
|
||||||
|
// 分析参数
|
||||||
|
stream << QStringLiteral(u"<div class='section-title'>分析参数</div>\n");
|
||||||
|
stream << "<table class='param-table'>\n";
|
||||||
|
stream << QStringLiteral(u"<tr><td>起始能量(keV):</td><td>%1</td><td>终止能量(keV):</td><td>%2</td></tr>\n")
|
||||||
|
.arg(formatDecimal(m_data.analysis.startEnergy, 2))
|
||||||
|
.arg(formatDecimal(m_data.analysis.endEnergy, 2));
|
||||||
|
stream << QStringLiteral(u"<tr><td>统计误差限值:</td><td>%1%</td><td>活度比例系数:</td><td>%2</td></tr>\n")
|
||||||
|
.arg(formatDecimal(m_data.analysis.statErrorLimit, 3))
|
||||||
|
.arg(formatScientific(m_data.analysis.activityRatio, 4));
|
||||||
|
stream << QStringLiteral(u"<tr><td>探测限计算方法:</td><td colspan='3'>%1</td></tr>\n")
|
||||||
|
.arg(m_data.analysis.mdaMethod);
|
||||||
|
stream << "</table>\n";
|
||||||
|
|
||||||
|
// 能谱峰一览表
|
||||||
|
stream << QStringLiteral(u"<div class='section-title'>能 谱 峰 一 览 表</div>\n");
|
||||||
|
stream << QStringLiteral(u"<table class='peak-table'>\n");
|
||||||
|
stream << QStringLiteral(u"<tr>\n");
|
||||||
|
stream << QStringLiteral(u"<th rowspan='2'>核素</th>\n");
|
||||||
|
stream << QStringLiteral(u"<th rowspan='2' colspan='1'>平均活度(贝克Bq)</th>\n");
|
||||||
|
stream << QStringLiteral(u"<th rowspan='2' colspan='1'>不确定度</th>\n");
|
||||||
|
stream << QStringLiteral(u"<th colspan='4'>峰</th>\n");
|
||||||
|
stream << QStringLiteral(u"<th rowspan='2'>备注</th>\n");
|
||||||
|
stream << QStringLiteral(u"</tr>\n");
|
||||||
|
stream << QStringLiteral(u"<tr>\n");
|
||||||
|
stream << QStringLiteral(u"<th>能量keV</th>\n");
|
||||||
|
stream << QStringLiteral(u"<th>活度(贝克Bq)</th>\n");
|
||||||
|
stream << QStringLiteral(u"<th>不确定度</th>\n");
|
||||||
|
stream << QStringLiteral(u"<th>最小可探测活度(MDA)(贝克Bq)</th>\n");
|
||||||
|
stream << QStringLiteral(u"</tr>\n");
|
||||||
|
|
||||||
|
for (const auto& peak : m_data.peaks) {
|
||||||
|
stream << QStringLiteral(u"<tr>\n");
|
||||||
|
stream << QStringLiteral(u"<td>%1</td>\n").arg(peak.nuclide);
|
||||||
|
stream << QStringLiteral(u"<td>%1</td>\n").arg(formatScientific(peak.avgActivity, 4));
|
||||||
|
stream << QStringLiteral(u"<td>%1%</td>\n").arg(formatDecimal(peak.avgUncertainty, 2));
|
||||||
|
stream << QStringLiteral(u"<td>%1</td>\n").arg(formatDecimal(peak.energy, 2));
|
||||||
|
stream << QStringLiteral(u"<td>%1</td>\n").arg(formatScientific(peak.peakActivity, 3));
|
||||||
|
stream << QStringLiteral(u"<td>%1%</td>\n").arg(formatDecimal(peak.peakUncertainty, 2));
|
||||||
|
stream << QStringLiteral(u"<td>%1</td>\n").arg(formatScientific(peak.mda, 3));
|
||||||
|
stream << QStringLiteral(u"<td>%1</td>\n").arg(peak.remark);
|
||||||
|
stream << QStringLiteral(u"</tr>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
stream << QStringLiteral(u"</table>\n");
|
||||||
|
|
||||||
|
// 峰提示码说明
|
||||||
|
stream << QStringLiteral(u"<div class='legend'>\n");
|
||||||
|
stream << QStringLiteral(u"<div class='legend-title'>峰提示码说明:</div>\n");
|
||||||
|
stream << QStringLiteral(u"<div>G - γ射线</div>\n");
|
||||||
|
stream << QStringLiteral(u"<div>X - X射线</div>\n");
|
||||||
|
stream << QStringLiteral(u"<div>ec - 内转换电子</div>\n");
|
||||||
|
stream << QStringLiteral(u"</div>\n");
|
||||||
|
// 签名
|
||||||
|
stream << "<div class='signature-section'>\n";
|
||||||
|
stream << QStringLiteral(u"<div class='signature-line'>分析员:%1</div>\n")
|
||||||
|
.arg(m_data.signature.analyst);
|
||||||
|
stream << QStringLiteral(u"<div class='signature-line'>审查员:%1</div>\n")
|
||||||
|
.arg(m_data.signature.reviewer);
|
||||||
|
stream << QStringLiteral(u"<div class='signature-line'>实验室:%1</div>\n")
|
||||||
|
.arg(m_data.signature.laboratory);
|
||||||
|
stream << QStringLiteral(u"<div class='signature-line'>日 期:%1</div>\n")
|
||||||
|
.arg(m_data.signature.reportDate.toString("yyyy年MM月dd日"));
|
||||||
|
stream << "</div>\n";
|
||||||
|
|
||||||
|
stream << "</body>\n";
|
||||||
|
stream << "</html>\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;
|
||||||
|
}
|
||||||
68
src/analysisReport/reportgenerator.h
Normal file
68
src/analysisReport/reportgenerator.h
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
#ifndef REPORTGENERATOR_H
|
||||||
|
#define REPORTGENERATOR_H
|
||||||
|
|
||||||
|
#include "spectrumdata.h"
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class ReportGenerator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ReportGenerator();
|
||||||
|
|
||||||
|
// 设置报告数据
|
||||||
|
void setData(const SpectrumReportData& data);
|
||||||
|
|
||||||
|
// 生成HTML格式报告
|
||||||
|
QString generateHtmlReport() const;
|
||||||
|
|
||||||
|
// 生成Word格式报告
|
||||||
|
QString generateWordReport() const;
|
||||||
|
|
||||||
|
// 生成简化版文本报告
|
||||||
|
QString generateTextReport() const;
|
||||||
|
|
||||||
|
// 保存报告到文件
|
||||||
|
bool saveToFile(const QString& filePath) const;
|
||||||
|
|
||||||
|
// 保存为Word文档
|
||||||
|
bool saveToWordFile(const QString& filePath) const;
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
SpectrumReportData m_data;
|
||||||
|
|
||||||
|
// 格式化数字为科学计数法字符串
|
||||||
|
QString formatScientific(double value, int precision = 4) const;
|
||||||
|
|
||||||
|
// 格式化浮点数
|
||||||
|
QString formatDecimal(double value, int precision = 2) const;
|
||||||
|
|
||||||
|
// 格式化日期时间
|
||||||
|
QString formatDateTime(const QDateTime& dt) const;
|
||||||
|
|
||||||
|
// 生成HTML头部
|
||||||
|
QString generateHtmlHeader() const;
|
||||||
|
|
||||||
|
// 生成测量参数部分
|
||||||
|
QString generateMeasurementSection() const;
|
||||||
|
|
||||||
|
// 生成刻度部分
|
||||||
|
QString generateCalibrationSection() const;
|
||||||
|
|
||||||
|
// 生成核素库部分
|
||||||
|
QString generateNuclideLibSection() const;
|
||||||
|
|
||||||
|
// 生成分析参数部分
|
||||||
|
QString generateAnalysisSection() const;
|
||||||
|
|
||||||
|
// 生成能谱峰一览表
|
||||||
|
QString generatePeakTableSection() const;
|
||||||
|
|
||||||
|
// 生成签名部分
|
||||||
|
QString generateSignatureSection() const;
|
||||||
|
|
||||||
|
// 生成HTML尾部
|
||||||
|
QString generateHtmlFooter() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // REPORTGENERATOR_H
|
||||||
345
src/analysisReport/reportwidget.cpp
Normal file
345
src/analysisReport/reportwidget.cpp
Normal file
|
|
@ -0,0 +1,345 @@
|
||||||
|
#include "reportwidget.h"
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QFormLayout>
|
||||||
|
#include <QGroupBox>
|
||||||
|
#include <QHeaderView>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QTextBrowser>
|
||||||
|
#include <QTextEdit>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QTableWidget>
|
||||||
|
ReportWidget::ReportWidget(QWidget *parent)
|
||||||
|
: QWidget(parent)
|
||||||
|
{
|
||||||
|
setupUi();
|
||||||
|
setupConnections();
|
||||||
|
loadSampleData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportWidget::setupUi()
|
||||||
|
{
|
||||||
|
auto* mainLayout = new QVBoxLayout(this);
|
||||||
|
|
||||||
|
// 顶部按钮栏
|
||||||
|
auto* btnLayout = new QHBoxLayout();
|
||||||
|
m_sampleBtn = new QPushButton("加载示例数据", this);
|
||||||
|
m_refreshBtn = new QPushButton("刷新报告", this);
|
||||||
|
m_exportHtmlBtn = new QPushButton("导出HTML", this);
|
||||||
|
m_exportWordBtn = new QPushButton("导出Word", this);
|
||||||
|
m_exportTextBtn = new QPushButton("导出文本", this);
|
||||||
|
|
||||||
|
btnLayout->addWidget(m_sampleBtn);
|
||||||
|
btnLayout->addStretch();
|
||||||
|
btnLayout->addWidget(m_refreshBtn);
|
||||||
|
btnLayout->addWidget(m_exportHtmlBtn);
|
||||||
|
btnLayout->addWidget(m_exportWordBtn);
|
||||||
|
btnLayout->addWidget(m_exportTextBtn);
|
||||||
|
mainLayout->addLayout(btnLayout);
|
||||||
|
|
||||||
|
// 标签页
|
||||||
|
m_tabWidget = new QTabWidget(this);
|
||||||
|
|
||||||
|
// HTML预览页
|
||||||
|
m_htmlView = new QTextBrowser(this);
|
||||||
|
m_htmlView->setOpenExternalLinks(true);
|
||||||
|
m_tabWidget->addTab(m_htmlView, "HTML预览");
|
||||||
|
|
||||||
|
// 文本预览页
|
||||||
|
m_textView = new QTextEdit(this);
|
||||||
|
m_textView->setReadOnly(true);
|
||||||
|
m_tabWidget->addTab(m_textView, "文本预览");
|
||||||
|
|
||||||
|
// 数据编辑页
|
||||||
|
m_dataEditWidget = new QWidget(this);
|
||||||
|
auto* dataLayout = new QVBoxLayout(m_dataEditWidget);
|
||||||
|
|
||||||
|
// 测量参数组
|
||||||
|
auto* measureGroup = new QGroupBox("测量参数", this);
|
||||||
|
auto* measureLayout = new QFormLayout(measureGroup);
|
||||||
|
m_spectrumFileEdit = new QLineEdit(this);
|
||||||
|
m_startTimeEdit = new QLineEdit(this);
|
||||||
|
m_liveTimeEdit = new QLineEdit(this);
|
||||||
|
m_realTimeEdit = new QLineEdit(this);
|
||||||
|
m_deadTimeEdit = new QLineEdit(this);
|
||||||
|
|
||||||
|
measureLayout->addRow("能谱文件:", m_spectrumFileEdit);
|
||||||
|
measureLayout->addRow("开始时间 (yyyy/M/d hh:mm:ss):", m_startTimeEdit);
|
||||||
|
measureLayout->addRow("活时间 (秒):", m_liveTimeEdit);
|
||||||
|
measureLayout->addRow("实时间 (秒):", m_realTimeEdit);
|
||||||
|
measureLayout->addRow("死时间 (%):", m_deadTimeEdit);
|
||||||
|
dataLayout->addWidget(measureGroup);
|
||||||
|
|
||||||
|
// 刻度参数组
|
||||||
|
auto* calibGroup = new QGroupBox("刻度参数", this);
|
||||||
|
auto* calibLayout = new QFormLayout(calibGroup);
|
||||||
|
m_calibFileEdit = new QLineEdit(this);
|
||||||
|
m_energyInterceptEdit = new QLineEdit(this);
|
||||||
|
m_energySlopeEdit = new QLineEdit(this);
|
||||||
|
m_energyQuadraticEdit = new QLineEdit(this);
|
||||||
|
|
||||||
|
calibLayout->addRow("刻度文件:", m_calibFileEdit);
|
||||||
|
calibLayout->addRow("能量截距 (keV):", m_energyInterceptEdit);
|
||||||
|
calibLayout->addRow("能量斜率 (keV/ch):", m_energySlopeEdit);
|
||||||
|
calibLayout->addRow("二次项系数 (keV/(ch^2)):", m_energyQuadraticEdit);
|
||||||
|
dataLayout->addWidget(calibGroup);
|
||||||
|
|
||||||
|
// 核素库与分析参数
|
||||||
|
auto* paramGroup = new QGroupBox("核素库与分析参数", this);
|
||||||
|
auto* paramLayout = new QFormLayout(paramGroup);
|
||||||
|
m_nuclideLibEdit = new QLineEdit(this);
|
||||||
|
m_peakMatchWidthEdit = new QLineEdit(this);
|
||||||
|
m_startEnergyEdit = new QLineEdit(this);
|
||||||
|
m_endEnergyEdit = new QLineEdit(this);
|
||||||
|
m_statErrorEdit = new QLineEdit(this);
|
||||||
|
|
||||||
|
paramLayout->addRow("核素库文件:", m_nuclideLibEdit);
|
||||||
|
paramLayout->addRow("峰匹配宽度 (*FWHM):", m_peakMatchWidthEdit);
|
||||||
|
paramLayout->addRow("起始能量 (keV):", m_startEnergyEdit);
|
||||||
|
paramLayout->addRow("终止能量 (keV):", m_endEnergyEdit);
|
||||||
|
paramLayout->addRow("统计误差限值 (%):", m_statErrorEdit);
|
||||||
|
dataLayout->addWidget(paramGroup);
|
||||||
|
|
||||||
|
// 峰数据表格
|
||||||
|
auto* peakGroup = new QGroupBox("能谱峰数据", this);
|
||||||
|
auto* peakLayout = new QVBoxLayout(peakGroup);
|
||||||
|
m_peakTable = new QTableWidget(this);
|
||||||
|
m_peakTable->setColumnCount(7);
|
||||||
|
m_peakTable->setHorizontalHeaderLabels(
|
||||||
|
QStringList() << "核素" << "平均活度(Bq)" << "能量(keV)"
|
||||||
|
<< "峰活度(Bq)" << "MDA(Bq)" << "提示码" << "备注");
|
||||||
|
m_peakTable->horizontalHeader()->setStretchLastSection(true);
|
||||||
|
m_peakTable->setRowCount(10); // 预留10行
|
||||||
|
peakLayout->addWidget(m_peakTable);
|
||||||
|
dataLayout->addWidget(peakGroup);
|
||||||
|
|
||||||
|
// 签名信息
|
||||||
|
auto* signGroup = new QGroupBox("签名信息", this);
|
||||||
|
auto* signLayout = new QFormLayout(signGroup);
|
||||||
|
m_analystEdit = new QLineEdit(this);
|
||||||
|
m_reviewerEdit = new QLineEdit(this);
|
||||||
|
m_laboratoryEdit = new QLineEdit(this);
|
||||||
|
m_reportDateEdit = new QLineEdit(this);
|
||||||
|
|
||||||
|
signLayout->addRow("分析员:", m_analystEdit);
|
||||||
|
signLayout->addRow("审查员:", m_reviewerEdit);
|
||||||
|
signLayout->addRow("实验室:", m_laboratoryEdit);
|
||||||
|
signLayout->addRow("报告日期 (yyyy-MM-dd):", m_reportDateEdit);
|
||||||
|
dataLayout->addWidget(signGroup);
|
||||||
|
|
||||||
|
dataLayout->addStretch();
|
||||||
|
m_tabWidget->addTab(m_dataEditWidget, "数据编辑");
|
||||||
|
|
||||||
|
mainLayout->addWidget(m_tabWidget);
|
||||||
|
|
||||||
|
resize(1000, 700);
|
||||||
|
setWindowTitle("能谱分析报告生成器");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportWidget::setupConnections()
|
||||||
|
{
|
||||||
|
connect(m_sampleBtn, &QPushButton::clicked, this, &ReportWidget::loadSampleData);
|
||||||
|
connect(m_refreshBtn, &QPushButton::clicked, this, &ReportWidget::refreshReport);
|
||||||
|
connect(m_exportHtmlBtn, &QPushButton::clicked, this, &ReportWidget::exportHtml);
|
||||||
|
connect(m_exportWordBtn, &QPushButton::clicked, this, &ReportWidget::exportWord);
|
||||||
|
connect(m_exportTextBtn, &QPushButton::clicked, this, &ReportWidget::exportText);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportWidget::setReportData(const SpectrumReportData &data)
|
||||||
|
{
|
||||||
|
m_data = data;
|
||||||
|
m_generator.setData(m_data);
|
||||||
|
|
||||||
|
// 更新UI
|
||||||
|
m_spectrumFileEdit->setText(m_data.measurement.spectrumFile);
|
||||||
|
m_startTimeEdit->setText(m_data.measurement.startTime.toString("yyyy/M/d hh:mm:ss"));
|
||||||
|
m_liveTimeEdit->setText(QString::number(m_data.measurement.liveTime));
|
||||||
|
m_realTimeEdit->setText(QString::number(m_data.measurement.realTime));
|
||||||
|
m_deadTimeEdit->setText(QString::number(m_data.measurement.deadTime));
|
||||||
|
|
||||||
|
m_calibFileEdit->setText(m_data.calibration.fileName);
|
||||||
|
m_energyInterceptEdit->setText(QString::number(m_data.calibration.energy.intercept));
|
||||||
|
m_energySlopeEdit->setText(QString::number(m_data.calibration.energy.slope));
|
||||||
|
m_energyQuadraticEdit->setText(QString::number(m_data.calibration.energy.quadratic, 'E', 3));
|
||||||
|
|
||||||
|
m_nuclideLibEdit->setText(m_data.nuclideLib.fileName);
|
||||||
|
m_peakMatchWidthEdit->setText(QString::number(m_data.nuclideLib.peakMatchWidth));
|
||||||
|
|
||||||
|
m_startEnergyEdit->setText(QString::number(m_data.analysis.startEnergy));
|
||||||
|
m_endEnergyEdit->setText(QString::number(m_data.analysis.endEnergy));
|
||||||
|
m_statErrorEdit->setText(QString::number(m_data.analysis.statErrorLimit));
|
||||||
|
|
||||||
|
m_analystEdit->setText(m_data.signature.analyst);
|
||||||
|
m_reviewerEdit->setText(m_data.signature.reviewer);
|
||||||
|
m_laboratoryEdit->setText(m_data.signature.laboratory);
|
||||||
|
m_reportDateEdit->setText(m_data.signature.reportDate.toString("yyyy-MM-dd"));
|
||||||
|
|
||||||
|
updatePeakTable();
|
||||||
|
refreshReport();
|
||||||
|
}
|
||||||
|
|
||||||
|
SpectrumReportData ReportWidget::reportData() const
|
||||||
|
{
|
||||||
|
return m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportWidget::refreshReport()
|
||||||
|
{
|
||||||
|
updateDataFromUi();
|
||||||
|
m_generator.setData(m_data);
|
||||||
|
|
||||||
|
// 更新HTML预览
|
||||||
|
m_htmlView->setHtml(m_generator.generateHtmlReport());
|
||||||
|
|
||||||
|
// 更新文本预览
|
||||||
|
m_textView->setPlainText(m_generator.generateTextReport());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportWidget::updateDataFromUi()
|
||||||
|
{
|
||||||
|
// 测量参数
|
||||||
|
m_data.measurement.spectrumFile = m_spectrumFileEdit->text();
|
||||||
|
m_data.measurement.startTime = QDateTime::fromString(m_startTimeEdit->text(), "yyyy/M/d hh:mm:ss");
|
||||||
|
m_data.measurement.liveTime = m_liveTimeEdit->text().toDouble();
|
||||||
|
m_data.measurement.realTime = m_realTimeEdit->text().toDouble();
|
||||||
|
m_data.measurement.deadTime = m_deadTimeEdit->text().toDouble();
|
||||||
|
|
||||||
|
// 刻度
|
||||||
|
m_data.calibration.fileName = m_calibFileEdit->text();
|
||||||
|
m_data.calibration.energy.intercept = m_energyInterceptEdit->text().toDouble();
|
||||||
|
m_data.calibration.energy.slope = m_energySlopeEdit->text().toDouble();
|
||||||
|
m_data.calibration.energy.quadratic = m_energyQuadraticEdit->text().toDouble();
|
||||||
|
|
||||||
|
// 核素库
|
||||||
|
m_data.nuclideLib.fileName = m_nuclideLibEdit->text();
|
||||||
|
m_data.nuclideLib.peakMatchWidth = m_peakMatchWidthEdit->text().toDouble();
|
||||||
|
|
||||||
|
// 分析参数
|
||||||
|
m_data.analysis.startEnergy = m_startEnergyEdit->text().toDouble();
|
||||||
|
m_data.analysis.endEnergy = m_endEnergyEdit->text().toDouble();
|
||||||
|
m_data.analysis.statErrorLimit = m_statErrorEdit->text().toDouble();
|
||||||
|
|
||||||
|
// 签名
|
||||||
|
m_data.signature.analyst = m_analystEdit->text();
|
||||||
|
m_data.signature.reviewer = m_reviewerEdit->text();
|
||||||
|
m_data.signature.laboratory = m_laboratoryEdit->text();
|
||||||
|
m_data.signature.reportDate = QDate::fromString(m_reportDateEdit->text(), "yyyy-MM-dd");
|
||||||
|
|
||||||
|
// 峰数据(从表格读取)
|
||||||
|
m_data.clearPeaks();
|
||||||
|
for (int row = 0; row < m_peakTable->rowCount(); ++row) {
|
||||||
|
QTableWidgetItem* nuclideItem = m_peakTable->item(row, 0);
|
||||||
|
if (!nuclideItem || nuclideItem->text().isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpectrumPeak peak;
|
||||||
|
peak.nuclide = nuclideItem->text();
|
||||||
|
|
||||||
|
QTableWidgetItem* avgItem = m_peakTable->item(row, 1);
|
||||||
|
if (avgItem) peak.avgActivity = avgItem->text().toDouble();
|
||||||
|
|
||||||
|
QTableWidgetItem* energyItem = m_peakTable->item(row, 2);
|
||||||
|
if (energyItem) peak.energy = energyItem->text().toDouble();
|
||||||
|
|
||||||
|
QTableWidgetItem* peakActItem = m_peakTable->item(row, 3);
|
||||||
|
if (peakActItem) peak.peakActivity = peakActItem->text().toDouble();
|
||||||
|
|
||||||
|
QTableWidgetItem* mdaItem = m_peakTable->item(row, 4);
|
||||||
|
if (mdaItem) peak.mda = mdaItem->text().toDouble();
|
||||||
|
|
||||||
|
QTableWidgetItem* codeItem = m_peakTable->item(row, 5);
|
||||||
|
if (codeItem) peak.peakCode = codeItem->text();
|
||||||
|
|
||||||
|
QTableWidgetItem* remarkItem = m_peakTable->item(row, 6);
|
||||||
|
if (remarkItem) peak.remark = remarkItem->text();
|
||||||
|
|
||||||
|
m_data.addPeak(peak);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportWidget::updatePeakTable()
|
||||||
|
{
|
||||||
|
m_peakTable->setRowCount(m_data.peakCount() + 5); // 多留几行
|
||||||
|
|
||||||
|
for (int i = 0; i < m_data.peakCount(); ++i) {
|
||||||
|
const auto& peak = m_data.peaks[i];
|
||||||
|
m_peakTable->setItem(i, 0, new QTableWidgetItem(peak.nuclide));
|
||||||
|
m_peakTable->setItem(i, 1, new QTableWidgetItem(QString::number(peak.avgActivity, 'E', 4)));
|
||||||
|
m_peakTable->setItem(i, 2, new QTableWidgetItem(QString::number(peak.energy, 'f', 2)));
|
||||||
|
m_peakTable->setItem(i, 3, new QTableWidgetItem(QString::number(peak.peakActivity, 'E', 3)));
|
||||||
|
m_peakTable->setItem(i, 4, new QTableWidgetItem(QString::number(peak.mda, 'E', 3)));
|
||||||
|
m_peakTable->setItem(i, 5, new QTableWidgetItem(peak.peakCode));
|
||||||
|
m_peakTable->setItem(i, 6, new QTableWidgetItem(peak.remark));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportWidget::exportHtml()
|
||||||
|
{
|
||||||
|
QString fileName = QFileDialog::getSaveFileName(
|
||||||
|
this, "导出HTML报告", "能谱分析报告.html",
|
||||||
|
"HTML文件 (*.html *.htm);;所有文件 (*.*)");
|
||||||
|
|
||||||
|
if (fileName.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDataFromUi();
|
||||||
|
m_generator.setData(m_data);
|
||||||
|
|
||||||
|
if (m_generator.saveToFile(fileName)) {
|
||||||
|
QMessageBox::information(this, "成功", "HTML报告导出成功!");
|
||||||
|
} else {
|
||||||
|
QMessageBox::warning(this, "失败", "导出失败,请检查文件路径。");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportWidget::exportWord()
|
||||||
|
{
|
||||||
|
QString fileName = QFileDialog::getSaveFileName(
|
||||||
|
this, "导出Word报告", "能谱分析报告.doc",
|
||||||
|
"Word文档 (*.doc);;所有文件 (*.*)");
|
||||||
|
|
||||||
|
if (fileName.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDataFromUi();
|
||||||
|
m_generator.setData(m_data);
|
||||||
|
|
||||||
|
if (m_generator.saveToWordFile(fileName)) {
|
||||||
|
QMessageBox::information(this, "成功", "Word报告导出成功!\n可用 Microsoft Word 或 WPS 打开查看。");
|
||||||
|
} else {
|
||||||
|
QMessageBox::warning(this, "失败", "导出失败,请检查文件路径。");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportWidget::exportText()
|
||||||
|
{
|
||||||
|
QString fileName = QFileDialog::getSaveFileName(
|
||||||
|
this, "导出文本报告", "能谱分析报告.txt",
|
||||||
|
"文本文件 (*.txt);;所有文件 (*.*)");
|
||||||
|
|
||||||
|
if (fileName.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDataFromUi();
|
||||||
|
m_generator.setData(m_data);
|
||||||
|
|
||||||
|
if (m_generator.saveToFile(fileName)) {
|
||||||
|
QMessageBox::information(this, "成功", "文本报告导出成功!");
|
||||||
|
} else {
|
||||||
|
QMessageBox::warning(this, "失败", "导出失败,请检查文件路径。");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportWidget::loadSampleData()
|
||||||
|
{
|
||||||
|
SpectrumReportData data;
|
||||||
|
data.fillSampleData();
|
||||||
|
setReportData(data);
|
||||||
|
}
|
||||||
96
src/analysisReport/reportwidget.h
Normal file
96
src/analysisReport/reportwidget.h
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
#ifndef REPORTWIDGET_H
|
||||||
|
#define REPORTWIDGET_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include "spectrumdata.h"
|
||||||
|
#include "reportgenerator.h"
|
||||||
|
|
||||||
|
class QTextEdit;
|
||||||
|
class QPushButton;
|
||||||
|
class QTabWidget;
|
||||||
|
class QTableWidget;
|
||||||
|
class QLabel;
|
||||||
|
class QLineEdit;
|
||||||
|
class QFormLayout;
|
||||||
|
class QTextBrowser;
|
||||||
|
|
||||||
|
class ReportWidget : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ReportWidget(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
// 设置报告数据
|
||||||
|
void setReportData(const SpectrumReportData& data);
|
||||||
|
|
||||||
|
// 获取当前数据
|
||||||
|
SpectrumReportData reportData() const;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
// 刷新报告显示
|
||||||
|
void refreshReport();
|
||||||
|
|
||||||
|
// 导出HTML报告
|
||||||
|
void exportHtml();
|
||||||
|
|
||||||
|
// 导出Word报告
|
||||||
|
void exportWord();
|
||||||
|
|
||||||
|
// 导出文本报告
|
||||||
|
void exportText();
|
||||||
|
|
||||||
|
// 加载示例数据
|
||||||
|
void loadSampleData();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setupUi();
|
||||||
|
void setupConnections();
|
||||||
|
void updateDataFromUi();
|
||||||
|
void updatePeakTable();
|
||||||
|
|
||||||
|
// UI组件
|
||||||
|
QTabWidget* m_tabWidget;
|
||||||
|
QTextBrowser* m_htmlView;
|
||||||
|
QTextEdit* m_textView;
|
||||||
|
QWidget* m_dataEditWidget;
|
||||||
|
|
||||||
|
// 数据编辑组件
|
||||||
|
QLineEdit* m_spectrumFileEdit;
|
||||||
|
QLineEdit* m_startTimeEdit;
|
||||||
|
QLineEdit* m_liveTimeEdit;
|
||||||
|
QLineEdit* m_realTimeEdit;
|
||||||
|
QLineEdit* m_deadTimeEdit;
|
||||||
|
|
||||||
|
QLineEdit* m_calibFileEdit;
|
||||||
|
QLineEdit* m_energyInterceptEdit;
|
||||||
|
QLineEdit* m_energySlopeEdit;
|
||||||
|
QLineEdit* m_energyQuadraticEdit;
|
||||||
|
|
||||||
|
QLineEdit* m_nuclideLibEdit;
|
||||||
|
QLineEdit* m_peakMatchWidthEdit;
|
||||||
|
|
||||||
|
QLineEdit* m_startEnergyEdit;
|
||||||
|
QLineEdit* m_endEnergyEdit;
|
||||||
|
QLineEdit* m_statErrorEdit;
|
||||||
|
|
||||||
|
QTableWidget* m_peakTable;
|
||||||
|
|
||||||
|
QLineEdit* m_analystEdit;
|
||||||
|
QLineEdit* m_reviewerEdit;
|
||||||
|
QLineEdit* m_laboratoryEdit;
|
||||||
|
QLineEdit* m_reportDateEdit;
|
||||||
|
|
||||||
|
// 按钮
|
||||||
|
QPushButton* m_refreshBtn;
|
||||||
|
QPushButton* m_exportHtmlBtn;
|
||||||
|
QPushButton* m_exportWordBtn;
|
||||||
|
QPushButton* m_exportTextBtn;
|
||||||
|
QPushButton* m_sampleBtn;
|
||||||
|
|
||||||
|
// 数据
|
||||||
|
SpectrumReportData m_data;
|
||||||
|
ReportGenerator m_generator;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // REPORTWIDGET_H
|
||||||
109
src/analysisReport/spectrumdata.cpp
Normal file
109
src/analysisReport/spectrumdata.cpp
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
#include "spectrumdata.h"
|
||||||
|
|
||||||
|
SpectrumReportData::SpectrumReportData()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpectrumReportData::addPeak(const SpectrumPeak &peak)
|
||||||
|
{
|
||||||
|
peaks.append(peak);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpectrumReportData::clearPeaks()
|
||||||
|
{
|
||||||
|
peaks.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SpectrumReportData::peakCount() const
|
||||||
|
{
|
||||||
|
return peaks.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpectrumReportData::fillSampleData()
|
||||||
|
{
|
||||||
|
// 测量参数
|
||||||
|
measurement.spectrumFile = "3#-20250416";
|
||||||
|
measurement.startTime = QDateTime(QDate(2025, 4, 16), QTime(20, 1, 22));
|
||||||
|
measurement.liveTime = 86400.0;
|
||||||
|
measurement.realTime = 86444.0;
|
||||||
|
measurement.deadTime = 0.05;
|
||||||
|
|
||||||
|
// 刻度信息
|
||||||
|
calibration.fileName = "刻度文件.Clb";
|
||||||
|
calibration.standardSource = "Co60";
|
||||||
|
|
||||||
|
// 能量刻度
|
||||||
|
calibration.energy.generateTime = QDateTime(QDate(2025, 3, 21), QTime(11, 3, 28));
|
||||||
|
calibration.energy.intercept = 0.057;
|
||||||
|
calibration.energy.slope = 0.090;
|
||||||
|
calibration.energy.quadratic = -3.127e-9;
|
||||||
|
|
||||||
|
// 效率刻度
|
||||||
|
calibration.efficiency.generateTime = QDateTime(QDate(2025, 3, 21), QTime(11, 2, 50));
|
||||||
|
calibration.efficiency.inflectionEnergy = 80.00;
|
||||||
|
calibration.efficiency.aboveInflection = "一次方程";
|
||||||
|
calibration.efficiency.aboveError = 0.0;
|
||||||
|
calibration.efficiency.belowInflection = "二次方程";
|
||||||
|
calibration.efficiency.belowError = 0.0;
|
||||||
|
calibration.efficiency.logEquation =
|
||||||
|
"-1.164361E+01 + (4.475904E+00*Log(E)) + (-5.221437E-01*Log(E)^2)";
|
||||||
|
|
||||||
|
// 核素库
|
||||||
|
nuclideLib.fileName = "Xe131m-131-133主要射线.Lib";
|
||||||
|
nuclideLib.peakMatchWidth = 0.500;
|
||||||
|
|
||||||
|
// 分析参数
|
||||||
|
analysis.startEnergy = 0.96;
|
||||||
|
analysis.endEnergy = 271.36;
|
||||||
|
analysis.statErrorLimit = 30.000;
|
||||||
|
analysis.activityRatio = 1.0;
|
||||||
|
analysis.mdaMethod = "传统方法";
|
||||||
|
|
||||||
|
// 能谱峰数据
|
||||||
|
peaks.clear();
|
||||||
|
|
||||||
|
SpectrumPeak peak1;
|
||||||
|
peak1.nuclide = "XE-133";
|
||||||
|
peak1.nuclideCode = "I";
|
||||||
|
peak1.avgActivity = 2.7056e-01;
|
||||||
|
peak1.avgUncertainty = 0.02;
|
||||||
|
peak1.energy = 81.00;
|
||||||
|
peak1.peakActivity = 2.706e-01;
|
||||||
|
peak1.peakUncertainty = 0.02;
|
||||||
|
peak1.mda = 3.393e-02;
|
||||||
|
peak1.peakCode = "@";
|
||||||
|
peak1.remark = "G";
|
||||||
|
peaks.append(peak1);
|
||||||
|
|
||||||
|
SpectrumPeak peak2;
|
||||||
|
peak2.nuclide = "XE-131M";
|
||||||
|
peak2.nuclideCode = "T";
|
||||||
|
peak2.avgActivity = 0.0;
|
||||||
|
peak2.avgUncertainty = 0.01;
|
||||||
|
peak2.energy = 163.93;
|
||||||
|
peak2.peakActivity = 2.220e-01;
|
||||||
|
peak2.peakUncertainty = 0.01;
|
||||||
|
peak2.mda = 4.506e-01;
|
||||||
|
peak2.peakCode = "%";
|
||||||
|
peak2.remark = "G";
|
||||||
|
peaks.append(peak2);
|
||||||
|
|
||||||
|
SpectrumPeak peak3;
|
||||||
|
peak3.nuclide = "XE-133M";
|
||||||
|
peak3.nuclideCode = "I";
|
||||||
|
peak3.avgActivity = 0.0;
|
||||||
|
peak3.avgUncertainty = 0.02;
|
||||||
|
peak3.energy = 233.22;
|
||||||
|
peak3.peakActivity = 0.0;
|
||||||
|
peak3.peakUncertainty = 0.02;
|
||||||
|
peak3.mda = 9.827e-02;
|
||||||
|
peak3.peakCode = "%";
|
||||||
|
peak3.remark = "G";
|
||||||
|
peaks.append(peak3);
|
||||||
|
|
||||||
|
// 签名信息
|
||||||
|
signature.analyst = "XESPM-III";
|
||||||
|
signature.reviewer = "管理员";
|
||||||
|
signature.laboratory = "GAMMASPEC";
|
||||||
|
signature.reportDate = QDate(2025, 11, 13);
|
||||||
|
}
|
||||||
114
src/analysisReport/spectrumdata.h
Normal file
114
src/analysisReport/spectrumdata.h
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
#ifndef SPECTRUMDATA_H
|
||||||
|
#define SPECTRUMDATA_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
|
// 能量刻度参数
|
||||||
|
struct EnergyCalibration {
|
||||||
|
QDateTime generateTime; // 生成时间
|
||||||
|
double intercept = 0.0; // 截距 (keV)
|
||||||
|
double slope = 0.0; // 斜率 (keV/ch)
|
||||||
|
double quadratic = 0.0; // 二次项系数 (keV/(ch^2))
|
||||||
|
};
|
||||||
|
|
||||||
|
// 效率刻度参数
|
||||||
|
struct EfficiencyCalibration {
|
||||||
|
QDateTime generateTime; // 生成时间
|
||||||
|
double inflectionEnergy = 0.0; // 拐点能量 (keV)
|
||||||
|
QString aboveInflection; // 拐点以上方法
|
||||||
|
double aboveError = 0.0; // 拐点以上误差
|
||||||
|
QString belowInflection; // 拐点以下方法
|
||||||
|
double belowError = 0.0; // 拐点以下误差
|
||||||
|
QString logEquation; // 效率对数方程式
|
||||||
|
};
|
||||||
|
|
||||||
|
// 刻度信息
|
||||||
|
struct Calibration {
|
||||||
|
QString fileName; // 刻度文件名
|
||||||
|
EnergyCalibration energy; // 能量刻度
|
||||||
|
EfficiencyCalibration efficiency; // 效率刻度
|
||||||
|
QString standardSource; // 刻度标准源
|
||||||
|
};
|
||||||
|
|
||||||
|
// 核素库信息
|
||||||
|
struct NuclideLibrary {
|
||||||
|
QString fileName; // 库文件名
|
||||||
|
double peakMatchWidth = 0.0; // 峰匹配宽度 (*FWHM, keV)
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分析参数
|
||||||
|
struct AnalysisParameters {
|
||||||
|
double startEnergy = 0.0; // 起始能量 (keV)
|
||||||
|
double endEnergy = 0.0; // 终止能量 (keV)
|
||||||
|
double statErrorLimit = 0.0; // 统计误差限值 (%)
|
||||||
|
double activityRatio = 0.0; // 活度比例系数
|
||||||
|
QString mdaMethod; // 探测限计算方法
|
||||||
|
};
|
||||||
|
|
||||||
|
// 单个峰数据
|
||||||
|
struct SpectrumPeak {
|
||||||
|
QString nuclide; // 核素名称
|
||||||
|
QString nuclideCode; // 核素提示码
|
||||||
|
double avgActivity = 0.0; // 平均活度 (Bq)
|
||||||
|
double avgUncertainty = 0.0; // 平均活度不确定度 (%)
|
||||||
|
double energy = 0.0; // 峰能量 (keV)
|
||||||
|
double peakActivity = 0.0; // 峰活度 (Bq)
|
||||||
|
double peakUncertainty = 0.0;// 峰活度不确定度 (%)
|
||||||
|
double mda = 0.0; // 最小可探测活度 MDA (Bq)
|
||||||
|
QString peakCode; // 峰提示码
|
||||||
|
QString remark; // 备注
|
||||||
|
};
|
||||||
|
|
||||||
|
// 测量参数
|
||||||
|
struct MeasurementParams {
|
||||||
|
QString spectrumFile; // 能谱文件名
|
||||||
|
QDateTime startTime; // 开始时间
|
||||||
|
double liveTime = 0.0; // 活时间 (秒)
|
||||||
|
double realTime = 0.0; // 实时间 (秒)
|
||||||
|
double deadTime = 0.0; // 死时间 (%)
|
||||||
|
};
|
||||||
|
|
||||||
|
// 报告签名信息
|
||||||
|
struct ReportSignature {
|
||||||
|
QString analyst; // 分析员
|
||||||
|
QString reviewer; // 审查员
|
||||||
|
QString laboratory; // 实验室
|
||||||
|
QDate reportDate; // 报告日期
|
||||||
|
};
|
||||||
|
|
||||||
|
// 完整的能谱报告数据
|
||||||
|
class SpectrumReportData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SpectrumReportData();
|
||||||
|
|
||||||
|
// 测量参数
|
||||||
|
MeasurementParams measurement;
|
||||||
|
|
||||||
|
// 刻度信息
|
||||||
|
Calibration calibration;
|
||||||
|
|
||||||
|
// 核素库
|
||||||
|
NuclideLibrary nuclideLib;
|
||||||
|
|
||||||
|
// 分析参数
|
||||||
|
AnalysisParameters analysis;
|
||||||
|
|
||||||
|
// 能谱峰列表
|
||||||
|
QVector<SpectrumPeak> peaks;
|
||||||
|
|
||||||
|
// 签名信息
|
||||||
|
ReportSignature signature;
|
||||||
|
|
||||||
|
// 工具方法
|
||||||
|
void addPeak(const SpectrumPeak& peak);
|
||||||
|
void clearPeaks();
|
||||||
|
int peakCount() const;
|
||||||
|
|
||||||
|
// 示例数据填充
|
||||||
|
void fillSampleData();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SPECTRUMDATA_H
|
||||||
23
src/src.pro
23
src/src.pro
|
|
@ -1,6 +1,8 @@
|
||||||
TARGET = EnergySpectrumAnalyer
|
TARGET = EnergySpectrumAnalyer
|
||||||
|
|
||||||
QT += core gui widgets concurrent datavisualization network sql
|
QT += core gui widgets concurrent datavisualization network sql xml
|
||||||
|
QT += gui-private
|
||||||
|
|
||||||
|
|
||||||
CONFIG += c++17 release
|
CONFIG += c++17 release
|
||||||
msvc {
|
msvc {
|
||||||
|
|
@ -41,7 +43,9 @@ INCLUDEPATH += \
|
||||||
$${PWD}/AntiConformEnergySpectrumView\
|
$${PWD}/AntiConformEnergySpectrumView\
|
||||||
$${PWD}/CoincidenceEventTimeView\
|
$${PWD}/CoincidenceEventTimeView\
|
||||||
$${PWD}/NuclideAnalysisView \
|
$${PWD}/NuclideAnalysisView \
|
||||||
$${PWD}/BackgroundTaskListView
|
$${PWD}/BackgroundTaskListView \
|
||||||
|
$${PWD}/analysisReport
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DEPENDPATH += \
|
DEPENDPATH += \
|
||||||
|
|
@ -64,7 +68,9 @@ DEPENDPATH += \
|
||||||
$${PWD}/AntiConformEnergySpectrumView\
|
$${PWD}/AntiConformEnergySpectrumView\
|
||||||
$${PWD}/CoincidenceEventTimeView\
|
$${PWD}/CoincidenceEventTimeView\
|
||||||
$${PWD}/NuclideAnalysisView \
|
$${PWD}/NuclideAnalysisView \
|
||||||
$${PWD}/BackgroundTaskListView
|
$${PWD}/BackgroundTaskListView \
|
||||||
|
$${PWD}/analysisReport
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
|
@ -78,6 +84,7 @@ SOURCES += \
|
||||||
CustomQwtPlot.cpp \
|
CustomQwtPlot.cpp \
|
||||||
DataProcessWorkPool.cpp \
|
DataProcessWorkPool.cpp \
|
||||||
DeviceConnectManagement.cpp \
|
DeviceConnectManagement.cpp \
|
||||||
|
EfficiencyScale.cpp \
|
||||||
EnergyCountPeakFitView/EnergyCountPeakFitView.cpp \
|
EnergyCountPeakFitView/EnergyCountPeakFitView.cpp \
|
||||||
EnergyCountPeakFitView/PeakFitParamsDialog.cpp \
|
EnergyCountPeakFitView/PeakFitParamsDialog.cpp \
|
||||||
EnergyCountPeakFitView/PlotRectItem.cpp \
|
EnergyCountPeakFitView/PlotRectItem.cpp \
|
||||||
|
|
@ -121,6 +128,9 @@ SOURCES += \
|
||||||
ConformToTheEnergySpectrum/ConformToTheEnergySpectrum.cpp \
|
ConformToTheEnergySpectrum/ConformToTheEnergySpectrum.cpp \
|
||||||
NuclideLib/NuclideLib.cpp \
|
NuclideLib/NuclideLib.cpp \
|
||||||
AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.cpp \
|
AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.cpp \
|
||||||
|
analysisReport/reportgenerator.cpp \
|
||||||
|
analysisReport/reportwidget.cpp \
|
||||||
|
analysisReport/spectrumdata.cpp \
|
||||||
main.cpp
|
main.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
|
|
@ -135,6 +145,7 @@ HEADERS += \
|
||||||
CustomQwtPlot.h \
|
CustomQwtPlot.h \
|
||||||
DataProcessWorkPool.h \
|
DataProcessWorkPool.h \
|
||||||
DeviceConnectManagement.h \
|
DeviceConnectManagement.h \
|
||||||
|
EfficiencyScale.h \
|
||||||
EnergyCountPeakFitView/EnergyCountPeakFitView.h \
|
EnergyCountPeakFitView/EnergyCountPeakFitView.h \
|
||||||
EnergyCountPeakFitView/PeakFitParamsDialog.h \
|
EnergyCountPeakFitView/PeakFitParamsDialog.h \
|
||||||
EnergyCountPeakFitView/PlotRectItem.h \
|
EnergyCountPeakFitView/PlotRectItem.h \
|
||||||
|
|
@ -179,13 +190,17 @@ HEADERS += \
|
||||||
EnergyCountPeakFitView/EnergyCountPeakFitView.h \
|
EnergyCountPeakFitView/EnergyCountPeakFitView.h \
|
||||||
ConformToTheEnergySpectrum/ConformToTheEnergySpectrum.h \
|
ConformToTheEnergySpectrum/ConformToTheEnergySpectrum.h \
|
||||||
NuclideLib/NuclideLib.h \
|
NuclideLib/NuclideLib.h \
|
||||||
AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.h
|
AntiConformEnergySpectrumView/AntiConformEnergySpectrumView.h \
|
||||||
|
analysisReport/reportgenerator.h \
|
||||||
|
analysisReport/reportwidget.h \
|
||||||
|
analysisReport/spectrumdata.h
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
2DSpectralCompliance/TwoDSpectralCompliance.ui \
|
2DSpectralCompliance/TwoDSpectralCompliance.ui \
|
||||||
AboutDlg.ui \
|
AboutDlg.ui \
|
||||||
CountRateAnalysisView/CountRateAnalysisView.ui \
|
CountRateAnalysisView/CountRateAnalysisView.ui \
|
||||||
DeviceConnectManagement.ui \
|
DeviceConnectManagement.ui \
|
||||||
|
EfficiencyScale.ui \
|
||||||
EnergyScaleForm.ui \
|
EnergyScaleForm.ui \
|
||||||
MainWindow.ui \
|
MainWindow.ui \
|
||||||
MeasureAnalysisHistoryForm/MeasureAnalysisHistoryForm.ui \
|
MeasureAnalysisHistoryForm/MeasureAnalysisHistoryForm.ui \
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user