Kaynağa Gözat

feat: safety inspect

YaoH 3 gün önce
ebeveyn
işleme
7b9caef8c3

+ 3 - 2
.clang-format

@@ -27,11 +27,12 @@ BreakBeforeBraces: Attach # 用于 if/for/while 等控制流语句,使其大
 AlignTrailingComments: true # 尾随注释的对齐
 
 # 指针/引用符
-PointerAndReferenceBindsToType: false # * 和 & 紧贴变量名 (e.g., int *x)
+# PointerAndReferenceBindsToType: false # * 和 & 紧贴变量名 (e.g., int *x)
 # 或 true 如果你喜欢紧贴类型 (e.g., int* x),Qt 官方更常用前者,但后者也常见。
 # 注意:Qt 官方指南里是这样写的:`char *ptr;` 但实际代码中 `char* ptr;` 也大量存在。
 
 # 其他常见的 Q_PROPERTY 相关的对齐
 AllowShortBlocksOnASingleLine: Empty # {} 可以放在一行
 
-# 确保在项目中安装了 Clang-Format VS Code 扩展,并设置为保存时格式化。
+# 确保在项目中安装了 Clang-Format VS Code 扩展,并设置为保存时格式化。
+

+ 36 - 2
CMakeLists.txt

@@ -9,11 +9,41 @@ set(CMAKE_AUTORCC ON)
 # 设置 C++ 标准
 set(CMAKE_CXX_STANDARD 17)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
-set(CMAKE_PREFIX_PATH "C:/Qt/6.9.0/msvc2022_64")
+set(CMAKE_CXX_EXTENSIONS OFF)
+
+
+if (APPLE)
+    message(STATUS "Compiling for macOS")
+
+    # macOS Clang 配置
+    set(CMAKE_C_COMPILER /opt/homebrew/opt/llvm/bin/clang)
+    set(CMAKE_CXX_COMPILER /opt/homebrew/opt/llvm/bin/clang++)
+
+    execute_process(
+        COMMAND xcrun --sdk macosx --show-sdk-path
+        OUTPUT_VARIABLE SDK_PATH
+        OUTPUT_STRIP_TRAILING_WHITESPACE
+    )
+
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
+    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ")
+
+elseif(WIN32)
+    message(STATUS "Compiling for Windows")
+
+    # Windows MSVC 默认不需要特别设置,但你也可以切换成 clang-cl:
+    # set(CMAKE_C_COMPILER "clang-cl")
+    # set(CMAKE_CXX_COMPILER "clang-cl")
+
+    # 推荐使用 vcpkg 来管理 Windows 下的库路径
+    # set(CMAKE_TOOLCHAIN_FILE "C:/vcpkg/scripts/buildsystems/vcpkg.cmake" CACHE STRING "")
+endif()
+
+#set(CMAKE_PREFIX_PATH "C:/Qt/6.9.0/msvc2022_64")
 
 
 # # 设置 OpenSSL 安装路径
- set(OPENSSL_ROOT_DIR "C:/Qt/Tools/OpenSSLv3/Win_x64")
+# set(OPENSSL_ROOT_DIR "C:/Qt/Tools/OpenSSLv3/Win_x64")
 
 # 查找 OpenSSL 库
 find_package(OpenSSL REQUIRED)
@@ -75,6 +105,8 @@ set(SOURCES
     serial/paregnrmc.cpp
     worker/timeupdatethread.cpp
     components/loadingWidget.cpp
+    components/custommessagebox.cpp
+    components/SafetyInspectDialog.cpp
     utils/backendapimanager.cpp
     homepage/homepage.cpp
     homepage/homepagefactory.cpp
@@ -127,6 +159,8 @@ set(HEADERS
     homepage/homepage.h
     worker/timeupdatethread.h
     components/loadingWidget.h
+    components/custommessagebox.h
+    components/SafetyInspectDialog.h
     utils/backendapimanager.h
 )
 

+ 21 - 2
blastJob/blastopepage.cpp

@@ -4,6 +4,7 @@
 #include <QProcessEnvironment>
 #include <QWebEngineSettings>
 
+#include "../components/custommessagebox.h"
 #include "../components/loadingwidget.h"
 #include "../login/loginwindow.h"
 #include "../registryManager/registrymanager.h"
@@ -20,9 +21,27 @@ const int ColIndexUuid = 9;
 BlastOpePage::BlastOpePage(QWidget *parent)
     : QWidget(parent), ui(new Ui::BlastOpePage), dao(DatabaseManager::getInstance().getDatabase()) {
     QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
+
+    bool isAllSafetyInspectorConfirmed = true;
+    const QJsonObject data = backendAPIManager::getSafetyInspect(QDate::currentDate().toString("yyyy-MM-dd"));
+    for (const QJsonValue &value : data["safetyInspectors"].toArray()) {
+        if (value.isObject()) {
+            if (value.toObject()["confirmTime"].toString() == "") {
+                isAllSafetyInspectorConfirmed = false;
+                break;
+            }
+        }
+    }
+    if (!isAllSafetyInspectorConfirmed) {
+        bool isContinue = CustomMessageBox::showConfirmDialog("安全检查未完成", "安全检查没有全部确认,是否继续?",
+                                                              "继续", "取消", this);
+
+        if (!isContinue) {
+            return;
+        }
+    }
     if (isFaceVerificationEnabled) {
         InitFace();
-
     } else {
         ui->setupUi(this);
         initPagination();
@@ -855,7 +874,7 @@ void BlastOpePage::triggerBatchFiringBlast() {
     for (auto it = uuidWidgetSMap.begin(); it != uuidWidgetSMap.end(); ++it) {
         QString uuid = it.key();
         firingWidget *widget = it.value();
-        QString topic = "hxgc/" + uuid + "/P";
+        QString topic = "hxgc/" + uuid + "/BlastTask";
         QString message = "起爆";
         widget->onCountdownFinished(topic, message);
     }

+ 28 - 0
blastProject/blastprojectpage.cpp

@@ -4,6 +4,7 @@
 #include <QJsonObject>
 #include <QUrl>
 
+#include "../components/SafetyInspectDialog.h"
 #include "../components/buttondelegate.h"
 #include "../components/loadingWidget.h"
 #include "../utils/backendapimanager.h"
@@ -341,3 +342,30 @@ QString BlastProjectPage::getUserNameByIds(const QStringList &userIds) {
 }
 
 BlastProjectPage::~BlastProjectPage() { delete ui; }
+
+void BlastProjectPage::on_showSafetyInspectBtn_clicked() {
+    const QString todayDateStr = QDate::currentDate().toString("yyyy-MM-dd");
+    SafetyInspectDialog *safetyInspect = new SafetyInspectDialog(this, m_userNameById, todayDateStr);
+    safetyInspect->setModal(false);
+    safetyInspect->setWindowTitle("安全检查");
+    safetyInspect->setDate(todayDateStr);
+    safetyInspect->show();
+
+    LoadingWidget::showLoading(this, "正在加载安全检查数据...");
+    const QJsonObject data = backendAPIManager::getSafetyInspect(todayDateStr);
+
+    QList<SafetyInspectDialog::InspectionRecord> inspectionRecordsList;
+    for (const QJsonValue &value : data["safetyInspectors"].toArray()) {
+        if (value.isObject()) {
+            QJsonObject obj = value.toObject();
+            SafetyInspectDialog::InspectionRecord record;
+            record.name = obj["userName"].toString();
+            record.confirmTime = obj["confirmTime"].toString();
+            record.phone = obj["phone"].toString();
+            inspectionRecordsList.append(record);
+        }
+    }
+    safetyInspect->setInspectionRecords(inspectionRecordsList);
+
+    LoadingWidget::hideLoading();
+}

+ 2 - 0
blastProject/blastprojectpage.h

@@ -30,6 +30,8 @@ class BlastProjectPage : public QWidget {
     void messageAndTopicReceived(const QByteArray &message, const QMqttTopicName &topic);
     void updateProjectUUId(QString uuid);
 
+    void on_showSafetyInspectBtn_clicked();
+
    private:
     void refreshData();
     void loadDataFromSource(int currentPage, int pageSize);

+ 19 - 0
blastProject/blastprojectpage.ui

@@ -99,6 +99,22 @@ QPushButton {
        </spacer>
       </item>
       <item>
+       <widget class="QPushButton" name="showSafetyInspectBtn">
+        <property name="minimumSize">
+         <size>
+          <width>130</width>
+          <height>40</height>
+         </size>
+        </property>
+        <property name="cursor">
+         <cursorShape>OpenHandCursor</cursorShape>
+        </property>
+        <property name="text">
+         <string>安检信息</string>
+        </property>
+       </widget>
+      </item>
+      <item>
        <widget class="QPushButton" name="pushButton">
         <property name="minimumSize">
          <size>
@@ -106,6 +122,9 @@ QPushButton {
           <height>40</height>
          </size>
         </property>
+        <property name="cursor">
+         <cursorShape>OpenHandCursor</cursorShape>
+        </property>
         <property name="text">
          <string>刷新</string>
         </property>

+ 79 - 0
components/SafetyInspectDialog.h

@@ -0,0 +1,79 @@
+#ifndef SAFETYINSPECT_H
+#define SAFETYINSPECT_H
+
+#include <QDialog>
+#include <QHBoxLayout>
+#include <QHeaderView>
+#include <QJsonArray>
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QLabel>
+#include <QNetworkAccessManager>
+#include <QNetworkReply>
+#include <QPushButton>
+#include <QTableWidget>
+#include <QVBoxLayout>
+
+/**
+ * SafetyInspect Dialog Component
+ *
+ * Usage example:
+ *
+ * // Method 1: Set data manually
+ * SafetyInspect *dialog = new SafetyInspect(this);
+ * dialog->setDate("2025-07-30");
+ *
+ * QList<SafetyInspect::InspectionRecord> records;
+ * SafetyInspect::InspectionRecord record1;
+ * record1.name = "张三";
+ * record1.phone = "13800138000";
+ * record1.checkStatus = "检查通过";
+ * records.append(record1);
+ *
+ * dialog->setInspectionRecords(records);
+ * dialog->exec();
+ *
+ * // Method 2: Fetch data from HTTP
+ * SafetyInspect *dialog = new SafetyInspect(this);
+ * dialog->fetchDataFromHttp("https://api.example.com/safety-inspection");
+ * dialog->exec();
+ */
+
+class SafetyInspectDialog : public QDialog {
+    Q_OBJECT
+
+   public:
+    struct InspectionRecord {
+        QString name;
+        QString phone;
+        QString confirmTime;
+    };
+
+    explicit SafetyInspectDialog(QWidget *parent = nullptr,
+                                 const QMap<QString, QString> &userNameById = QMap<QString, QString>(),
+                                 const QString &dateStr = QString());
+    ~SafetyInspectDialog();
+
+    // Set the date to display in header
+    void setDate(const QString &date);
+
+    // Set the inspection records to display in table
+    void setInspectionRecords(const QList<InspectionRecord> &records);
+
+    void onCloseButtonClicked();
+
+   private:
+    void setupUI();
+    void setupTable();
+    void populateTable();
+
+    QLabel *m_dateLabel;
+    QTableWidget *m_tableWidget;
+    QPushButton *m_closeButton;
+
+    QString m_currentDate;
+    QMap<QString, QString> m_userNameById;
+    QList<InspectionRecord> m_inspectionRecords;
+};
+
+#endif  // SAFETYINSPECT_H

+ 40 - 0
components/custommessagebox.cpp

@@ -0,0 +1,40 @@
+#include "custommessagebox.h"
+
+CustomMessageBox::CustomMessageBox(QWidget *parent) : QMessageBox(parent) {}
+
+bool CustomMessageBox::showConfirmDialog(const QString &title, const QString &text, const QString &yesButtonText,
+                                         const QString &noButtonText, QWidget *parent) {
+    QMessageBox msgBox(parent);
+    msgBox.setWindowTitle(title);
+    msgBox.setText(text);
+
+    QPushButton *yesButton = msgBox.addButton(yesButtonText, QMessageBox::YesRole);
+    QPushButton *noButton = msgBox.addButton(noButtonText, QMessageBox::NoRole);
+
+    // 设置按钮样式
+    yesButton->setStyleSheet(
+        "QPushButton { background-color:rgb(5, 58, 156); color: white; padding: 5px 15px; "
+        "border-radius: 4px; }");
+    noButton->setStyleSheet(
+        "QPushButton { background-color: #f44336; color: white; padding: 5px 15px; "
+        "border-radius: 4px; }");
+
+    msgBox.exec();
+
+    // 返回true表示用户选择了确定/继续,false表示取消
+    return msgBox.clickedButton() == yesButton;
+}
+
+bool CustomMessageBox::showTimeoutDialog(const QString &title, const QString &text, const QString &continueButtonText,
+                                         const QString &cancelButtonText, QWidget *parent) {
+    return showConfirmDialog(title, text, continueButtonText, cancelButtonText, parent);
+}
+
+void CustomMessageBox::setupButtonStyles(QPushButton *yesButton, QPushButton *noButton) {
+    yesButton->setStyleSheet(
+        "QPushButton { background-color:rgb(5, 58, 156); color: white; padding: 5px 15px; "
+        "border-radius: 4px; }");
+    noButton->setStyleSheet(
+        "QPushButton { background-color: #f44336; color: white; padding: 5px 15px; "
+        "border-radius: 4px; }");
+}

+ 26 - 0
components/custommessagebox.h

@@ -0,0 +1,26 @@
+#ifndef CUSTOMMESSAGEBOX_H
+#define CUSTOMMESSAGEBOX_H
+
+#include <QMessageBox>
+#include <QPushButton>
+
+class CustomMessageBox : public QMessageBox {
+    Q_OBJECT
+
+   public:
+    explicit CustomMessageBox(QWidget *parent = nullptr);
+
+    // 显示确认对话框,返回用户选择的结果
+    static bool showConfirmDialog(const QString &title, const QString &text, const QString &yesButtonText = "确定",
+                                  const QString &noButtonText = "取消", QWidget *parent = nullptr);
+
+    // 显示超时等待确认对话框
+    static bool showTimeoutDialog(const QString &title, const QString &text,
+                                  const QString &continueButtonText = "继续等待",
+                                  const QString &cancelButtonText = "强制取消", QWidget *parent = nullptr);
+
+   private:
+    void setupButtonStyles(QPushButton *yesButton, QPushButton *noButton);
+};
+
+#endif  // CUSTOMMESSAGEBOX_H

+ 138 - 0
components/safetyInspectDialog.cpp

@@ -0,0 +1,138 @@
+#include "SafetyInspectDialog.h"
+
+#include <QApplication>
+#include <QMessageBox>
+#include <QScreen>
+
+SafetyInspectDialog::SafetyInspectDialog(QWidget *parent, const QMap<QString, QString> &userNameById,
+                                         const QString &dateStr)
+    : QDialog(parent),
+      m_dateLabel(nullptr),
+      m_tableWidget(nullptr),
+      m_closeButton(nullptr),
+      m_currentDate(dateStr),
+      m_userNameById(userNameById) {
+    setupUI();
+}
+
+SafetyInspectDialog::~SafetyInspectDialog() {}
+
+void SafetyInspectDialog::setupUI() {
+    setWindowTitle("安全检查记录");
+    setModal(true);
+    resize(600, 400);
+
+    // Center the dialog
+    QScreen *screen = QApplication::primaryScreen();
+    if (screen) {
+        QRect screenGeometry = screen->geometry();
+        int x = (screenGeometry.width() - width()) / 2;
+        int y = (screenGeometry.height() - height()) / 2;
+        move(x, y);
+    }
+
+    // Main layout
+    QVBoxLayout *mainLayout = new QVBoxLayout(this);
+    mainLayout->setContentsMargins(20, 20, 20, 20);
+    mainLayout->setSpacing(15);
+
+    // Header section
+    QHBoxLayout *headerLayout = new QHBoxLayout();
+    QLabel *titleLabel = new QLabel("检查日期:");
+    titleLabel->setStyleSheet("font-weight: bold; font-size: 14px; color: #333;");
+
+    m_dateLabel = new QLabel("未设置");
+    m_dateLabel->setStyleSheet("font-size: 14px; color: #666; padding: 5px;");
+
+    headerLayout->addWidget(titleLabel);
+    headerLayout->addWidget(m_dateLabel);
+    headerLayout->addStretch();
+
+    mainLayout->addLayout(headerLayout);
+
+    // Table setup
+    setupTable();
+    mainLayout->addWidget(m_tableWidget);
+
+    // Button section
+    QHBoxLayout *buttonLayout = new QHBoxLayout();
+    m_closeButton = new QPushButton("关闭");
+    m_closeButton->setStyleSheet(
+        "QPushButton { "
+        "background-color: #007ACC; "
+        "color: white; "
+        "padding: 8px 20px; "
+        "border-radius: 4px; "
+        "border: none; "
+        "font-size: 12px; "
+        "} "
+        "QPushButton:hover { "
+        "background-color: #005a9e; "
+        "} "
+        "QPushButton:pressed { "
+        "background-color: #004578; "
+        "}");
+
+    connect(m_closeButton, &QPushButton::clicked, this, &SafetyInspectDialog::onCloseButtonClicked);
+
+    buttonLayout->addStretch();
+    buttonLayout->addWidget(m_closeButton);
+
+    mainLayout->addLayout(buttonLayout);
+}
+
+void SafetyInspectDialog::setupTable() {
+    m_tableWidget = new QTableWidget(this);
+    m_tableWidget->setColumnCount(3);
+
+    QStringList headers;
+    headers << "姓名" << "电话" << "检查状态";
+    m_tableWidget->setHorizontalHeaderLabels(headers);
+
+    // Configure table properties
+    m_tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
+    m_tableWidget->setAlternatingRowColors(true);
+    m_tableWidget->verticalHeader()->setVisible(false);
+
+    // Set column widths
+    m_tableWidget->horizontalHeader()->setStretchLastSection(true);
+    m_tableWidget->setColumnWidth(0, 150);  // Name column
+    m_tableWidget->setColumnWidth(1, 180);  // Phone column
+    // Status column will stretch to fill remaining space
+}
+
+void SafetyInspectDialog::setDate(const QString &date) {
+    m_currentDate = date;
+    if (m_dateLabel) {
+        m_dateLabel->setText(date);
+    }
+}
+
+void SafetyInspectDialog::setInspectionRecords(const QList<InspectionRecord> &records) {
+    m_inspectionRecords = records;
+    populateTable();
+}
+
+void SafetyInspectDialog::populateTable() {
+    if (!m_tableWidget) return;
+
+    m_tableWidget->setRowCount(m_inspectionRecords.size());
+
+    for (int i = 0; i < m_inspectionRecords.size(); ++i) {
+        const InspectionRecord &record = m_inspectionRecords[i];
+
+        m_tableWidget->setItem(i, 0, new QTableWidgetItem(record.name));
+        m_tableWidget->setItem(i, 1, new QTableWidgetItem(record.phone));
+
+        if (record.confirmTime != QString()) {
+            QString formattedTime = record.confirmTime.left(16).replace('T', ' ');
+            QTableWidgetItem *timeItem = new QTableWidgetItem(formattedTime);
+            timeItem->setForeground(QColor(Qt::darkGreen));
+            m_tableWidget->setItem(i, 2, timeItem);
+        } else {
+            m_tableWidget->setItem(i, 2, new QTableWidgetItem("未确认"));
+        }
+    }
+}
+
+void SafetyInspectDialog::onCloseButtonClicked() { accept(); }

+ 25 - 36
fireWidget/firingwidget.cpp

@@ -27,7 +27,7 @@
 firingWidget::firingWidget(const int &row, const bool &select, const QString &uuid, QWidget *parent)
     : QWidget(parent),
       ui(new Ui::firingWidget),
-      m_curProjUuid(uuid),
+      m_blasterDevUuid(uuid),
       m_row(row),
       m_select(select),
       daoProj(DatabaseManager::getInstance().getDatabase()),
@@ -44,13 +44,13 @@ firingWidget::firingWidget(const int &row, const bool &select, const QString &uu
     ui->scrollArea->setStyleSheet("background: rgba(0, 0, 0, 22); border-radius: 20px;");
     ui->verticalLayout->addWidget(navProgress);
     // TODO
-    m_curProjUuid = "61c93e60e50e3439";
-    m_topic = "hxgc/" + m_curProjUuid + "/BlastTaskReply";
-    qDebug() << ANSI_COLOR_GREEN << "Firing widget created with topic: " << m_topic << ANSI_COLOR_RESET;
-    QStringList topics = {m_topic};
+    m_blasterDevUuid = "61c93e60e50e3439";
+    m_blasterPubTopic = "hxgc/" + m_blasterDevUuid + "/BlastTaskReply";
+    qDebug() << ANSI_COLOR_GREEN << "Firing widget created with topic: " << m_blasterPubTopic << ANSI_COLOR_RESET;
+    QStringList topics = {m_blasterPubTopic};
     m_connectionCheckTimer = new QTimer(this);
 
-    m_subscription = mainMqttClient->subscribeToTopic(m_topic);
+    m_subscription = mainMqttClient->subscribeToTopic(m_blasterPubTopic);
     connect(m_subscription, &QMqttSubscription::messageReceived, this, &firingWidget::handleProjectFiringMqttMessage);
 
     connect(this, &firingWidget::lastStageChanged, this, &firingWidget::handleFiringStageChanged);
@@ -75,9 +75,9 @@ void firingWidget::sendMqttMessage(const QString &topic, const QByteArray &messa
 void firingWidget::startBlasting() {
     // 等待3s mqtt连接后再发送mqtt消息
     m_lastStage = FiringStages::Starting;
-    qDebug() << ANSI_COLOR_GREEN << "Firing widget started with topic: 1" << m_topic << ANSI_COLOR_RESET;
+    qDebug() << ANSI_COLOR_GREEN << "Firing widget started with topic: 1" << m_blasterPubTopic << ANSI_COLOR_RESET;
     emit lastStageChanged(FiringStages::Starting);
-    qDebug() << ANSI_COLOR_GREEN << "Firing widget started with topic: 2" << m_topic << ANSI_COLOR_RESET;
+    qDebug() << ANSI_COLOR_GREEN << "Firing widget started with topic: 2" << m_blasterPubTopic << ANSI_COLOR_RESET;
     checkBlasterConnection();
 }
 
@@ -93,7 +93,7 @@ void firingWidget::checkBlasterConnection() {
             m_connectionCheckTimer->stop();
             return;
         }
-        if (m_lastMsgTime.secsTo(QDateTime::currentDateTime()) > 3) {
+        if (m_lastMsgTime.secsTo(QDateTime::currentDateTime()) > 10) {
             m_connectionCheckTimer->stop();
             QMessageBox msgBox;
             msgBox.setWindowTitle("起爆检测测试错误");
@@ -111,10 +111,10 @@ void firingWidget::checkBlasterConnection() {
                 emit lastStageChanged(FiringStages::ForceCanceled);
                 return;
             }
-            m_connectionCheckTimer->start(5000);
+            m_connectionCheckTimer->start(10000);
         }
     });
-    m_connectionCheckTimer->start(1000);
+    m_connectionCheckTimer->start(10000);
 }
 
 void firingWidget::handleProjectFiringMqttMessage(const QMqttMessage &message) {
@@ -134,7 +134,7 @@ void firingWidget::handleProjectFiringMqttMessage(const QMqttMessage &message) {
                 int status = relayInfo["status"].toInt();
                 if (ErrorBlastStatus::isErrorStatus(status)) {
                     Logger::getInstance().error(QString("爆破器返回异常. 工程uuid: %1; 错误code: %2")
-                                                    .arg(m_curProjUuid, ErrorBlastStatus::getErrorMessage(status)));
+                                                    .arg(m_blasterDevUuid, ErrorBlastStatus::getErrorMessage(status)));
                     QMessageBox::critical(nullptr, "爆破器报错",
                                           QString("错误错误信息: %1").arg(ErrorBlastStatus::getErrorMessage(status)));
                     sendCancelFiringMsg();
@@ -212,10 +212,10 @@ void firingWidget::handleProjectFiringMqttMessage(const QMqttMessage &message) {
                             ui->pushButton_2->setEnabled(false);
                             emit progressChanged(FiringStages::BlastFinished, m_row);
                             emit updatefiringStage(FiringStages::BlastFinished, m_row);
-                            emit updateProjectStatus(m_curProjUuid, BlastStatus::Blasted);
+                            emit updateProjectStatus(m_blasterDevUuid, BlastStatus::Blasted);
                             ui->pushButton_2->setText("已完成起爆");
                             navProgress->setState(FiringStages::BlastFinished);
-                            emit closeFiring(m_curProjUuid, m_row);
+                            emit closeFiring(m_blasterDevUuid, m_row);
                             break;
                         case FiringStages::CancelConfirmed:
                             navProgress->setState(FiringStages::BlastFinished);
@@ -224,8 +224,8 @@ void firingWidget::handleProjectFiringMqttMessage(const QMqttMessage &message) {
 
                             emit progressChanged(FiringStages::Starting, m_row);
                             emit updatefiringStage(FiringStages::CancelConfirmed, m_row);
-                            emit updateProjectStatus(m_curProjUuid, BlastStatus::Created);
-                            emit closeFiring(m_curProjUuid, m_row);
+                            emit updateProjectStatus(m_blasterDevUuid, BlastStatus::Created);
+                            emit closeFiring(m_blasterDevUuid, m_row);
                             break;
                         default:
                             break;
@@ -244,11 +244,11 @@ void firingWidget::onCountdownFinished(const QString &topic, const QString &mess
 }
 
 void firingWidget::onMqttDisconnected() {
-    Logger::getInstance().info(QString("Project(%1) firing MQTT disconncted.").arg(m_curProjUuid));
+    Logger::getInstance().info(QString("Project(%1) firing MQTT disconncted.").arg(m_blasterDevUuid));
 }
 
 void firingWidget::onMqttConnected() {
-    Logger::getInstance().info(QString("Project(%1) firing MQTT connected.").arg(m_curProjUuid));
+    Logger::getInstance().info(QString("Project(%1) firing MQTT connected.").arg(m_blasterDevUuid));
 }
 
 void firingWidget::onButtonPressedReceived(const QString &topic, const QString &message) {
@@ -259,26 +259,15 @@ void firingWidget::onButtonPressedReceived(const QString &topic, const QString &
         Logger::getInstance().error(QString("onButtonPressedReceived: Failed to send data: %1").arg(data));
         return;
     }
-    emit countdown(m_curProjUuid, topic, message);
+    emit countdown(m_blasterDevUuid, topic, message);
     qDebug() << "Data sent successfully";
 }
 
-void firingWidget::onSafeChecked(const QString projectUuid) {
-    if (projectUuid == m_curProjUuid) {
-        m_lastStage = 3;  // 设置为待安全确认状态
-        emit projSafeCheckSuccess(m_curProjUuid);
-        emit lastStageChanged(m_lastStage);
-        qDebug() << ANSI_COLOR_GREEN << "安全确认成功,进入待起爆状态" << ANSI_COLOR_RESET;
-    } else {
-        qDebug() << "Project UUID mismatch, expected: " << m_curProjUuid << ", got: " << projectUuid;
-    }
-}
-
 // 状态改变
 void firingWidget::handleFiringStageChanged(int newStage) {
     qDebug() << ANSI_COLOR_GREEN << "handleFiringStageChanged: " << newStage << ANSI_COLOR_RESET;
-    m_curProjUuid = "61c93e60e50e3439";
-    QString topic = "hxgc/" + m_curProjUuid + "/BlastTask";
+    m_blasterDevUuid = "61c93e60e50e3439";
+    QString topic = "hxgc/" + m_blasterDevUuid + "/BlastTask";
     QString message;
     QString buttonText;
     switch (newStage) {
@@ -316,9 +305,9 @@ void firingWidget::handleFiringStageChanged(int newStage) {
         case FiringStages::ForceCanceled:
             // 强制取消
             sendCancelFiringMsg();
-            emit updateProjectStatus(m_curProjUuid, BlastStatus::Created);
+            emit updateProjectStatus(m_blasterDevUuid, BlastStatus::Created);
             emit updatefiringStage(FiringStages::ForceCanceled, m_row);
-            emit closeFiring(m_curProjUuid, m_row);
+            emit closeFiring(m_blasterDevUuid, m_row);
             break;
         default:
 
@@ -350,7 +339,7 @@ void firingWidget::handleFiringStageChanged(int newStage) {
             }
         } else if (m_lastStage == FiringStages::NetChargingFinished && m_select) {
             qDebug() << "多台起爆:待起爆状态";
-            emit batchFiringSignal(m_curProjUuid);
+            emit batchFiringSignal(m_blasterDevUuid);
         } else {
             qDebug() << "Stage 值变为: " << newStage << "发送消息" << message.toUtf8();
         }
@@ -359,6 +348,6 @@ void firingWidget::handleFiringStageChanged(int newStage) {
 
 void firingWidget::sendCancelFiringMsg() {
     QString message = "取消流程";
-    QString topic = "hxgc/" + m_curProjUuid + "/BlastTask";
+    QString topic = "hxgc/" + m_blasterDevUuid + "/BlastTask";
     sendMqttMessage(topic, message.toUtf8());
 }

+ 2 - 3
fireWidget/firingwidget.h

@@ -69,7 +69,6 @@ class firingWidget : public QWidget {
    private:
     void checkBlasterConnection();
     void sendMqttMessage(const QString &topic, const QByteArray &message);
-    void onSafeChecked(const QString projectUuid);
 
    private:
     Ui::firingWidget *ui;
@@ -79,8 +78,8 @@ class firingWidget : public QWidget {
     HBlastRegRecordDao daoReg;
     NavProgress *navProgress;
     SerialTool *serialTool = nullptr;
-    QString m_curProjUuid;
-    QString m_topic;  // firingwidget对应的 MQTT 主题
+    QString m_blasterDevUuid;
+    QString m_blasterPubTopic;  // firingwidget对应的 MQTT 主题
     int m_row;
     int m_lastStage = -1;  // 用于记录上一次的 stage 状态
     bool m_select;

+ 23 - 85
utils/backendapimanager.cpp

@@ -101,14 +101,17 @@ QNetworkReply *backendAPIManager::sendRequest(const QString &endpoint, const QJs
 
     return reply;
 }
-QJsonObject backendAPIManager::getBlastRecords(int page, int pageSize, QJsonObject params) {
+
+QJsonObject backendAPIManager::getSafetyInspect(QString dateStr) {
     if (!s_instance) return QJsonObject();
     s_instance->requestSuccess = false;
 
-    params.insert("page", QString::number(page));
-    params.insert("pageSize", QString::number(pageSize));
+    QJsonObject params;
+    params.insert("page", 1);
+    params.insert("pageSize", 1);
+    params.insert("dutyDate", dateStr);
 
-    QNetworkReply *reply = s_instance->sendRequest("blastrecord", params, "GET");
+    QNetworkReply *reply = s_instance->sendRequest("h-safety-inspect", params, "GET");
 
     QEventLoop loop;
     QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
@@ -117,37 +120,38 @@ QJsonObject backendAPIManager::getBlastRecords(int page, int pageSize, QJsonObje
     QJsonObject result;
     if (reply->error() == QNetworkReply::NoError) {
         QJsonDocument response = QJsonDocument::fromJson(reply->readAll());
-        result = response.object()["data"].toObject();
+        if (response.object()["code"].toInt() != 200) {
+            // TODO:
+            return QJsonObject();
+        }
+        result = response.object()["data"].toObject()["list"].toArray().first().toObject();
     }
 
     reply->deleteLater();
     return result;
 }
 
-// TODO: not use any more 上传爆破记录完整记录. 包含设备和雷管记录
-bool backendAPIManager::uploadBlastProjectFull(const QJsonObject &projectData) {
-    if (!s_instance) return false;
-
+QJsonObject backendAPIManager::getBlastRecords(int page, int pageSize, QJsonObject params) {
+    if (!s_instance) return QJsonObject();
     s_instance->requestSuccess = false;
-    QNetworkReply *reply = s_instance->sendRequest("blastrecord/pc", projectData, "POST");
 
-    // 使用事件循环等待响应
+    params.insert("page", QString::number(page));
+    params.insert("pageSize", QString::number(pageSize));
+
+    QNetworkReply *reply = s_instance->sendRequest("blastrecord", params, "GET");
+
     QEventLoop loop;
     QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
     loop.exec();
 
+    QJsonObject result;
     if (reply->error() == QNetworkReply::NoError) {
         QJsonDocument response = QJsonDocument::fromJson(reply->readAll());
-        s_instance->handleReponseOKFinished(response, reply->url());
-    } else {
-        Logger::getInstance().error(QString("UploadBlastProjectFull request failed. uuid: %1 error message: %2")
-                                        .arg(projectData.value("uuid").toString())
-                                        .arg(reply->errorString()));
-        s_instance->handleResponseError(reply->errorString());
+        result = response.object()["data"].toObject();
     }
 
     reply->deleteLater();
-    return s_instance->requestSuccess;
+    return result;
 }
 
 QJsonObject backendAPIManager::getHProjects(int page, int pageSize, QJsonObject extParams) {
@@ -243,73 +247,7 @@ QJsonArray backendAPIManager::getHAddresses() {
     return result;
 }
 
-bool backendAPIManager::uploadBlastProject(const QJsonObject &projectData) {
-    if (!s_instance) return false;
-
-    s_instance->requestSuccess = false;
-    QNetworkReply *reply = s_instance->sendRequest("blastrecord", projectData, "POST");
-
-    // 使用事件循环等待响应
-    QEventLoop loop;
-    QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
-    loop.exec();
-
-    if (reply->error() == QNetworkReply::NoError) {
-        QJsonDocument response = QJsonDocument::fromJson(reply->readAll());
-        s_instance->handleReponseOKFinished(response, reply->url());
-    } else {
-        s_instance->handleResponseError(reply->errorString());
-    }
-
-    reply->deleteLater();
-    return s_instance->requestSuccess;
-}
-
-bool backendAPIManager::uploadBlastProjectDets(const QJsonObject &detsData) {
-    if (!s_instance) return false;
-
-    s_instance->requestSuccess = false;
-    QNetworkReply *reply = s_instance->sendRequest("blastrecorddet/batch", detsData, "POST");
-
-    // 使用事件循环等待响应
-    QEventLoop loop;
-    QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
-    loop.exec();
-
-    if (reply->error() == QNetworkReply::NoError) {
-        QJsonDocument response = QJsonDocument::fromJson(reply->readAll());
-        s_instance->handleReponseOKFinished(response, reply->url());
-    } else {
-        s_instance->handleResponseError(reply->errorString());
-    }
-
-    reply->deleteLater();
-    return s_instance->requestSuccess;
-}
-
-bool backendAPIManager::uploadBlastEquipments(const QJsonObject &regDetsData) {
-    if (!s_instance) return false;
-
-    s_instance->requestSuccess = false;
-    QNetworkReply *reply = s_instance->sendRequest("blastrecordequipment", regDetsData, "POST");
-
-    // 使用事件循环等待响应
-    QEventLoop loop;
-    QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
-    loop.exec();
-
-    if (reply->error() == QNetworkReply::NoError) {
-        QJsonDocument response = QJsonDocument::fromJson(reply->readAll());
-        s_instance->handleReponseOKFinished(response, reply->url());
-    } else {
-        s_instance->handleResponseError(reply->errorString());
-    }
-
-    reply->deleteLater();
-    return s_instance->requestSuccess;
-}
-
-void backendAPIManager::handleReponseOKFinished(const QJsonDocument &response, const QUrl &url) {
+void backendAPIManager::handleResponseOKFinished(const QJsonDocument &response, const QUrl &url) {
     // Check response status
     if (response.object().contains("code")) {
         int code = response.object()["code"].toInt();

+ 2 - 4
utils/backendapimanager.h

@@ -17,15 +17,13 @@ class backendAPIManager : public QObject {
     static void cleanup();
     static void setAuthToken(const QString &token);
 
-    static bool uploadBlastProjectFull(const QJsonObject &projectData);
-    static bool uploadBlastProject(const QJsonObject &projectData);
-    static bool uploadBlastProjectDets(const QJsonObject &detsData);
     static bool uploadBlastEquipments(const QJsonObject &regDetsData);
     static QJsonObject getHProjects(int page, int pageSize, QJsonObject extParams);
     static QJsonArray getSysUsers();
     static QJsonArray getHAddresses();
     static QJsonArray getDailyBlastedCount(int days);
     static QJsonObject getBlastRecords(int page, int pageSize, QJsonObject params);
+    static QJsonObject getSafetyInspect(QString dateStr);
 
    signals:
     void uploadFinished(const QJsonDocument &response);
@@ -47,7 +45,7 @@ class backendAPIManager : public QObject {
     QString authToken;
 
    private slots:
-    void handleReponseOKFinished(const QJsonDocument &response, const QUrl &url);
+    void handleResponseOKFinished(const QJsonDocument &response, const QUrl &url);
     void handleResponseError(const QString &error);
 };
 

+ 27 - 0
utils/global.h

@@ -108,4 +108,31 @@ const static int ForceCanceled = 11;              // 强制取消
 }  // namespace FiringStages
 // namespace FiringStages
 
+static QString GetFiringStageName(int stage) {
+    switch (stage) {
+        case FiringStages::Starting:
+            return "待起爆";
+        case FiringStages::QuickTesting:
+            return "起爆检测中";
+        case FiringStages::QuickTestFinished:
+            return "检测完成";
+        case FiringStages::NetCharging:
+            return "充电中";
+        case FiringStages::NetChargingFinished:
+            return "充电完成";
+        case FiringStages::Blasting:
+            return "起爆中";
+        case FiringStages::BlastFinished:
+            return "起爆完成";
+        case FiringStages::CancelConfirmed:
+            return "已取消";
+        case FiringStages::PendingTriggerButtonClick:
+            return "按下双键起爆...";
+        case FiringStages::ForceCanceled:
+            return "已强制取消";
+        default:
+            return "未知状态";
+    }
+}
+
 #endif  // GLOBAL_H