Преглед изворни кода

feat: 添加安全验证流程

YaoH пре 19 часа
родитељ
комит
e755810a4d

+ 2 - 0
CMakeLists.txt

@@ -9,6 +9,8 @@ set(CMAKE_AUTORCC ON)
 # 设置 C++ 标准
 set(CMAKE_CXX_STANDARD 17)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_PREFIX_PATH "/opt/homebrew/Cellar/qt/6.9.0")
+
 
 # # 设置 OpenSSL 安装路径
  set(OPENSSL_ROOT_DIR "C:/Qt/Tools/OpenSSLv3/Win_x64")

+ 4 - 0
README.md

@@ -35,5 +35,9 @@
    目前一些请求需要cookie, 所以需要从登录页面进入才可以。
 5. 如何添加用户?
    访问后端APP。菜单: 基础信息 -> 人员管理。添加爆破员,操作员。
+
+6. 安全员控制逻辑。
+   安全员汇报的地址可能包含多个爆破工程,但一个爆破工程不会上报多次地址。
    
 ### TODOs:
+ 

+ 1 - 1
backendapimanager.cpp

@@ -107,7 +107,7 @@ QJsonArray backendAPIManager::getSysUsers() {
     return result;
 }
 
-QJsonArray backendAPIManager::getPcs() {
+QJsonArray backendAPIManager::getHAddresses() {
     if (!s_instance) return QJsonArray();
 
     QNetworkReply *reply = s_instance->sendRequest("h-address/pc", QJsonObject(), "GET");

+ 1 - 1
backendapimanager.h

@@ -22,7 +22,7 @@ class backendAPIManager : public QObject {
     static bool uploadBlastProjectDets(const QJsonObject &detsData);
     static bool uploadBlastEquipments(const QJsonObject &regDetsData);
     static QJsonArray getSysUsers();
-    static QJsonArray getPcs();
+    static QJsonArray getHAddresses();
 
    signals:
     void uploadFinished(const QJsonDocument &response);

+ 10 - 10
blastProject/HProjectDao.h

@@ -1,12 +1,14 @@
 #ifndef HPROJECTDAO_H
 #define HPROJECTDAO_H
 
+#include <QList>
+#include <QMessageBox>
 #include <QObject>
 #include <QSqlDatabase>
-#include <QSqlQuery>
 #include <QSqlError>
-#include <QList>
+#include <QSqlQuery>
 #include <QSqlRecord>
+
 #include "HProject.h"
 
 struct PaginatedHProjectResult {
@@ -14,10 +16,8 @@ struct PaginatedHProjectResult {
     int totalCount;
 };
 
-class HProjectDao
-{
-
-public:
+class HProjectDao {
+   public:
     HProjectDao(QSqlDatabase db);
     bool addHProject(const HProject &project);
     bool updateHProject(const HProject &project);
@@ -26,13 +26,13 @@ public:
     HProject getHProjectById(qint64 id);
     PaginatedHProjectResult getAllHProjects(int page, int pageSize);
     PaginatedHProjectResult getAllHProjectsByOpera(int page, int pageSize);
-    QList<QSharedPointer<HProject> > getAllHProjectsReg();
+    QList<QSharedPointer<HProject>> getAllHProjectsReg();
+    QList<QSharedPointer<HProject>> getPendingSafeCheckProjByAddress(QList<QString> addressUuids);
 
-private:
+   private:
     QSqlDatabase database;
     // 将QSqlRecord转换为HProject对象
     QSharedPointer<HProject> recordToProject(const QSqlRecord &record);
-
 };
 
-#endif // HPROJECTDAO_H
+#endif  // HPROJECTDAO_H

+ 1 - 1
blastProject/blastprojectpage.cpp

@@ -24,7 +24,7 @@ BlastProjectPage::BlastProjectPage(QWidget *parent)
     RefreshData();
 
     dialog = new ProjectDialog(this);
-    QJsonArray pcs = backendAPIManager::getPcs();
+    QJsonArray pcs = backendAPIManager::getHAddresses();
     addressOptions(pcs);
     QJsonArray sysUsersObj = backendAPIManager::getSysUsers();
     personOptionsByType(sysUsersObj);

+ 80 - 56
blastProject/hprojectdao.cpp

@@ -1,16 +1,18 @@
 #include "HProjectDao.h"
 
+HProjectDao::HProjectDao(QSqlDatabase db) : database(db) {}
 
-HProjectDao::HProjectDao(QSqlDatabase db):database(db)
-{
-}
-
-bool HProjectDao::addHProject(const HProject &project)
-{
-
+bool HProjectDao::addHProject(const HProject &project) {
     QSqlQuery query;
-    query.prepare("INSERT INTO h_project (uuid, name, company_code, htid, xmbh, operator_name, operator_identity, blaster_name, blaster_identity, address_uuid, lora_address,pc_sn, det_sum, file_name, file_url, blast_status,blast_count,created_at, updated_at, deleted_at, create_by, update_by) "
-                  "VALUES (:uuid, :name, :companyCode, :htid, :xmbh, :operatorName, :operatorIdentity, :blasterName, :blasterIdentity, :addressUuid,:loraAddress, :pcSn, :detSum, :fileName, :fileUrl, :blastStatus, :blastCount,:createdAt, :updatedAt, :deletedAt, :createBy, :updateBy)");
+    query.prepare(
+        "INSERT INTO h_project (uuid, name, company_code, htid, xmbh, operator_name, "
+        "operator_identity, blaster_name, blaster_identity, address_uuid, lora_address,pc_sn, "
+        "det_sum, file_name, file_url, blast_status,blast_count,created_at, updated_at, "
+        "deleted_at, create_by, update_by) "
+        "VALUES (:uuid, :name, :companyCode, :htid, :xmbh, :operatorName, :operatorIdentity, "
+        ":blasterName, :blasterIdentity, :addressUuid,:loraAddress, :pcSn, :detSum, :fileName, "
+        ":fileUrl, :blastStatus, :blastCount,:createdAt, :updatedAt, :deletedAt, :createBy, "
+        ":updateBy)");
 
     query.bindValue(":uuid", project.getUuid());
     query.bindValue(":name", project.getName());
@@ -42,31 +44,31 @@ bool HProjectDao::addHProject(const HProject &project)
     return true;
 }
 
-bool HProjectDao::updateHProject(const HProject &project)
-{
+bool HProjectDao::updateHProject(const HProject &project) {
     QSqlQuery query;
-    query.prepare("UPDATE h_project SET "
-                  "uuid = :uuid, "
-                  "name = :name, "
-                  "company_code = :companyCode, "
-                  "htid = :htid, "
-                  "xmbh = :xmbh, "
-                  "operator_name = :operatorName, "
-                  "operator_identity = :operatorIdentity, "
-                  "blaster_name = :blasterName, "
-                  "blaster_identity = :blasterIdentity, "
-                  "address_uuid = :addressUuid, "
-                  "pc_sn = :pcSn, "
-                  "det_sum = :detSum, "
-                  "file_name = :fileName, "
-                  "file_url = :fileUrl, "
-                  "blast_status = :blastStatus, "
-                  "created_at = :createdAt, "
-                  "updated_at = :updatedAt, "
-                  "deleted_at = :deletedAt, "
-                  "create_by = :createBy, "
-                  "update_by = :updateBy "
-                  "WHERE id = :id");
+    query.prepare(
+        "UPDATE h_project SET "
+        "uuid = :uuid, "
+        "name = :name, "
+        "company_code = :companyCode, "
+        "htid = :htid, "
+        "xmbh = :xmbh, "
+        "operator_name = :operatorName, "
+        "operator_identity = :operatorIdentity, "
+        "blaster_name = :blasterName, "
+        "blaster_identity = :blasterIdentity, "
+        "address_uuid = :addressUuid, "
+        "pc_sn = :pcSn, "
+        "det_sum = :detSum, "
+        "file_name = :fileName, "
+        "file_url = :fileUrl, "
+        "blast_status = :blastStatus, "
+        "created_at = :createdAt, "
+        "updated_at = :updatedAt, "
+        "deleted_at = :deletedAt, "
+        "create_by = :createBy, "
+        "update_by = :updateBy "
+        "WHERE id = :id");
 
     query.bindValue(":id", project.getId());
     query.bindValue(":uuid", project.getUuid());
@@ -97,8 +99,7 @@ bool HProjectDao::updateHProject(const HProject &project)
     return true;
 }
 
-bool HProjectDao::deleteHProject(const HProject &project)
-{
+bool HProjectDao::deleteHProject(const HProject &project) {
     QSqlQuery query;
     query.prepare("DELETE FROM h_project WHERE id = :id");
     query.bindValue(":id", project.getId());
@@ -119,8 +120,7 @@ bool HProjectDao::deleteHProject(const HProject &project)
 //     return HProject();
 // }
 
-PaginatedHProjectResult HProjectDao::getAllHProjects(int page, int pageSize)
-{
+PaginatedHProjectResult HProjectDao::getAllHProjects(int page, int pageSize) {
     QList<QSharedPointer<HProject>> projects;
     QSqlQuery query(database);
     int offset = (page - 1) * pageSize;
@@ -129,7 +129,6 @@ PaginatedHProjectResult HProjectDao::getAllHProjects(int page, int pageSize)
     query.bindValue(":offset", offset);
 
     if (query.exec()) {
-
         while (query.next()) {
             projects.append(recordToProject(query.record()));
         }
@@ -142,15 +141,16 @@ PaginatedHProjectResult HProjectDao::getAllHProjects(int page, int pageSize)
     if (query.exec() && query.next()) {
         totalCount = query.value(0).toInt();
     }
-    return { projects, totalCount };
+    return {projects, totalCount};
 }
 
-PaginatedHProjectResult HProjectDao::getAllHProjectsByOpera(int page, int pageSize)
-{
+PaginatedHProjectResult HProjectDao::getAllHProjectsByOpera(int page, int pageSize) {
     QList<QSharedPointer<HProject>> projects;
     QSqlQuery query(database);
     int offset = (page - 1) * pageSize;
-    query.prepare("SELECT * FROM h_project WHERE blast_status >1 and blast_status <3 ORDER BY created_at LIMIT :pageSize OFFSET :offset");
+    query.prepare(
+        "SELECT * FROM h_project WHERE blast_status >1 and blast_status <3 ORDER BY created_at "
+        "LIMIT :pageSize OFFSET :offset");
     query.bindValue(":pageSize", pageSize);
     query.bindValue(":offset", offset);
     if (query.exec()) {
@@ -166,11 +166,33 @@ PaginatedHProjectResult HProjectDao::getAllHProjectsByOpera(int page, int pageSi
     if (query.exec() && query.next()) {
         totalCount = query.value(0).toInt();
     }
-    return { projects, totalCount };
+    return {projects, totalCount};
+}
+
+QList<QSharedPointer<HProject>> HProjectDao::getPendingSafeCheckProjByAddress(
+    QList<QString> addressUuids) {
+    QList<QSharedPointer<HProject>> projects;
+    QSqlQuery query(database);
+    QString placeholders = QString(",").repeated(addressUuids.size() - 1).prepend(":addressUuid");
+    query.prepare("SELECT * FROM h_project WHERE address_uuid IN (" + placeholders +
+                  ") "
+                  "AND blast_status = 2 ORDER BY created_at");
+
+    for (const QString &addressUuid : addressUuids) {
+        query.bindValue(":addressUuid", addressUuid);
+        if (!query.exec()) {
+            QMessageBox::critical(nullptr, "安全确认处理异常",
+                                  QString("查询工程数据异常: %1").arg(query.lastError().text()));
+            return projects;
+        }
+        while (query.next()) {
+            projects.append(recordToProject(query.record()));
+        }
+    }
+    return projects;
 }
 
-QList<QSharedPointer<HProject>> HProjectDao::getAllHProjectsReg()
-{
+QList<QSharedPointer<HProject>> HProjectDao::getAllHProjectsReg() {
     QList<QSharedPointer<HProject>> projects;
     QSqlQuery query(database);
     query.prepare("SELECT * FROM h_project WHERE blast_status =1 ORDER BY created_at ");
@@ -185,13 +207,13 @@ QList<QSharedPointer<HProject>> HProjectDao::getAllHProjectsReg()
     return projects;
 }
 
-//更改状态
-bool HProjectDao::updateBlastStatusByUuid(const QString &uuid, const QString &blastStatus)
-{
+// 更改状态
+bool HProjectDao::updateBlastStatusByUuid(const QString &uuid, const QString &blastStatus) {
     QSqlQuery query;
-    query.prepare("UPDATE h_project SET "
-                  "blast_status = :blastStatus "
-                  "WHERE uuid = :uuid");
+    query.prepare(
+        "UPDATE h_project SET "
+        "blast_status = :blastStatus "
+        "WHERE uuid = :uuid");
     query.bindValue(":uuid", uuid);
     query.bindValue(":blastStatus", blastStatus);
 
@@ -203,8 +225,7 @@ bool HProjectDao::updateBlastStatusByUuid(const QString &uuid, const QString &bl
     return true;
 }
 
-QSharedPointer<HProject> HProjectDao::recordToProject(const QSqlRecord &record)
-{
+QSharedPointer<HProject> HProjectDao::recordToProject(const QSqlRecord &record) {
     QSharedPointer<HProject> project = QSharedPointer<HProject>::create();
     project->setId(record.value("id").toInt());
     project->setUuid(record.value("uuid").toString());
@@ -223,9 +244,12 @@ QSharedPointer<HProject> HProjectDao::recordToProject(const QSqlRecord &record)
     project->setFileName(record.value("file_name").toString());
     project->setFileUrl(record.value("file_url").toString());
     project->setBlastStatus(record.value("blast_status").toString());
-    project->setCreatedAt(QDateTime::fromString(record.value("created_at").toString(), Qt::ISODateWithMs));
-    project->setUpdatedAt(QDateTime::fromString(record.value("updated_at").toString(), Qt::ISODateWithMs));
-    project->setDeletedAt(QDateTime::fromString(record.value("deleted_at").toString(), Qt::ISODateWithMs));
+    project->setCreatedAt(
+        QDateTime::fromString(record.value("created_at").toString(), Qt::ISODateWithMs));
+    project->setUpdatedAt(
+        QDateTime::fromString(record.value("updated_at").toString(), Qt::ISODateWithMs));
+    project->setDeletedAt(
+        QDateTime::fromString(record.value("deleted_at").toString(), Qt::ISODateWithMs));
     project->setCreateBy(record.value("create_by").toInt());
     project->setUpdateBy(record.value("update_by").toInt());
     return project;

+ 1 - 1
blastRecord/hblastrecord.cpp

@@ -93,7 +93,7 @@ QDateTime HBlastRecord::getDeletedAt() const { return deletedAt; }
 void HBlastRecord::setDeletedAt(const QDateTime &newDeletedAt) { deletedAt = newDeletedAt; }
 
 void HBlastRecord::setIsOfflineBlast(bool isOfflineBlast) { isOfflineBlast = isOfflineBlast; }
-bool HBlastRecord::getIsOfflineBlast() const { qDebug() << "isOfflineBlast value:" << isOfflineBlast; return isOfflineBlast; }
+bool HBlastRecord::getIsOfflineBlast() const { return isOfflineBlast; }
 
 qint64 HBlastRecord::getCreateBy() const { return createBy; }
 

+ 6 - 11
blastopepage.cpp

@@ -93,7 +93,6 @@ void BlastOpePage::InitFace() {
             }
         }
     }
-    qDebug() << "certifyUrl: " << certifyUrl;
     if (!certifyUrl.isEmpty()) {
         view->load(QUrl(certifyUrl));
 
@@ -124,7 +123,7 @@ void BlastOpePage::closeWebViewAndRestoreUI() {
 
 // 槽函数:处理 URL 改变事件
 void BlastOpePage::onUrlChanged(const QUrl &newUrl) {
-    LoadingWidget::showLoading(this, "跳转验证页...");
+    LoadingWidget::showLoading(this, "查询验证结果...");
     if (newUrl.host() == "www.integrateblaster.com") {
         closeWebViewAndRestoreUI();
         QNetworkAccessManager manager;
@@ -236,14 +235,6 @@ QJsonObject BlastOpePage::getMetaInfo() {
     QString certName;
     QString certNo;
 
-    // TODO: 获取登录用户信息
-    // QProcessEnvironment env = QProcessEnvironment::systemEnvironment();  //  获取系统环境变量
-    // if (env.contains("certName") && env.contains("certNo")) {
-    //     certName = env.value("certName", "");  // 第二个参数为默认值
-    //     certNo = env.value("certNo", "");
-    //     qDebug() << "Environment variables 'certName' or 'certNo' not found.";
-    //     return metaInfo;  // 如果没有找到相关环境变量,返回空的 QJsonObject
-    // } else {
     QMap<QString, QString> userInfo = RegistryManager::instance()->getCurentLoginUser();
     certName = userInfo.value("certName", "");
     certNo = userInfo.value("identity", "");
@@ -321,10 +312,14 @@ void BlastOpePage::loadDataFromSource(int currentPage, int pageSize) {
                         item = new QStandardItem(statusText);
                         item->setForeground(QColor("#e7c66b"));
                     } else if (value.toString() == "2") {
-                        statusText = "待 起 爆";
+                        statusText = "待安全确认";
                         item = new QStandardItem(statusText);
                         item->setForeground(QColor("#f3a361"));
                     } else if (value.toString() == "3") {
+                        statusText = "已安全确认";
+                        item = new QStandardItem(statusText);
+                        item->setForeground(QColor("#f3a361"));
+                    } else if (value.toString() == "4") {
                         statusText = "起 爆 完 成";
                         item = new QStandardItem(statusText);
                         item->setForeground(QColor("#90d543"));

+ 27 - 18
fireWidget/firingwidget.cpp

@@ -13,10 +13,6 @@
 #include <QUrl>
 #include <QUrlQuery>
 
-#include "../backendapimanager.h"
-#include "../countdownwidget.h"
-#include "../global.h"
-#include "../logger.h"
 #include "ui_firingwidget.h"
 
 #define ANSI_COLOR_GREEN "\x1B[32m"
@@ -48,9 +44,10 @@ firingWidget::firingWidget(const int &row, const bool &select, const QString &uu
     mqttThread->start();
     connect(mqttThread, &MqttThread::messageAndTopicReceived, this,
             &firingWidget::handleMessageAndTopic);
-
     connect(this, &firingWidget::lastStageChanged, this, &firingWidget::onLastStageChanged);
+    connect(this, &firingWidget::projSafeChckSuccess, this, &firingWidget::onLastStageChanged);
     connect(this, &firingWidget::updateData, this, &firingWidget::onBlastSucess);
+    connect(this, &firingWidget::safeChecked, this, &firingWidget::onSafeChecked);
     startBlasting();
 }
 
@@ -183,18 +180,17 @@ void firingWidget::handleMessageAndTopic(const QByteArray &message, const QMqttT
                             ui->pushButton_2->setEnabled(false);
                             emit progressChanged(3, m_row);
                             emit updateBlastStatus(3, m_row);
-                            ui->pushButton_2->setText("充电");
+                            ui->pushButton_2->setText("待确认");
                             navProgress->setState(3);
                             break;
                         case 4:
-                            ui->pushButton_2->setEnabled(true);
-                            emit progressChanged(4, m_row);
-                            emit updateBlastStatus(4, m_row);
-                            ui->pushButton_2->setText("起爆");
+                            ui->pushButton_2->setEnabled(false);
+                            ui->pushButton_2->setText("待确认");
                             navProgress->setState(4);
+                            emit updateBlastStatus(4, m_row);
                             break;
                         case 5:
-                            ui->pushButton_2->setEnabled(false);
+                            ui->pushButton_2->setEnabled(true);
                             emit progressChanged(5, m_row);
                             emit updateBlastStatus(5, m_row);
                             emit updateButton(5, m_row);
@@ -253,6 +249,17 @@ void firingWidget::onButtonPressedReceived(const QString &topic, const QString &
     qDebug() << "Data sent successfully";
 }
 
+void firingWidget::onSafeChecked(const QString projectUuid) {
+    if (projectUuid == m_uuid) {
+        lastStage = 3;  // 设置为待安全确认状态
+        emit projSafeChckSuccess(m_uuid);
+        emit lastStageChanged(lastStage);
+        qDebug() << ANSI_COLOR_GREEN << "安全确认成功,进入待起爆状态" << ANSI_COLOR_RESET;
+    } else {
+        qDebug() << "Project UUID mismatch, expected: " << m_uuid << ", got: " << projectUuid;
+    }
+}
+
 // 状态改变
 void firingWidget::onLastStageChanged(int newStage) {
     QString topic = "hxgc/" + m_uuid + "/P";
@@ -264,13 +271,17 @@ void firingWidget::onLastStageChanged(int newStage) {
             buttonText = "立即测试";
             sendMqttMessage(topic, message.toUtf8());
             break;
-        case 2:
+        case 2:  // 进入充电
             message = "开始充电";
             buttonText = "充电";
             sendMqttMessage(topic, message.toUtf8());
             break;
-        case 4:
-            message = "起爆";
+        case 3:  // 充电完成
+            message = "待安全确认";
+            // buttonText = "起爆";
+            break;
+        case 4:  // 充电完成
+            message = "待起爆";
             buttonText = "起爆";
             break;
         case 5:
@@ -297,7 +308,7 @@ void firingWidget::onLastStageChanged(int newStage) {
     Logger::getInstance().info(
         QString("Stage changed to: %1, sending message: %2").arg(newStage).arg(message));
     if (!message.isEmpty()) {
-        if (lastStage == 4 && !m_select) {
+        if (lastStage == 3 && !m_select) {
             bool success2;
             serialTool = SerialTool::getInstance(nullptr, &success2);
             if (serialTool) {
@@ -344,8 +355,6 @@ void firingWidget::onBlastSucess(const QJsonObject &jsonObj) {
     Logger::getInstance("blastRecord.log")
         .info(QJsonDocument(jsonObj).toJson(QJsonDocument::Indented));
     blast_uuid = QUuid::createUuid().toString(QUuid::WithoutBraces).remove(QRegularExpression("-"));
-    lat = labLat;
-    lon = labLon;
 
     saveAndUploadRecord(jsonObj);
 }
@@ -504,4 +513,4 @@ QList<HBlastRecordDet *> firingWidget::recordBlastProjectDets(const QString proj
         }
     }
     return recordDets;
-}
+}

+ 5 - 0
fireWidget/firingwidget.h

@@ -4,12 +4,14 @@
 #include <QJsonObject>
 #include <QWidget>
 
+#include "../backendapimanager.h"
 #include "../blastRecord/hblastrecord.h"
 #include "../blastRecord/hblastrecorddao.h"
 #include "../blastRecordDet/hblastrecorddetdao.h"
 #include "../blastRegRecord/hblastregrecorddao.h"
 #include "../databasemanager.h"
 #include "../des3encryption.h"
+#include "../logger.h"
 #include "../mqtt/mqttclient.h"
 #include "../mqttthread.h"
 #include "../serial/serialtool.h"
@@ -46,11 +48,13 @@ class firingWidget : public QWidget {
    signals:
     void progressChanged(int value, int row);
     void lastStageChanged(int newStage);
+    void projSafeChckSuccess(QString projectUuid);
     void updateBlastStatus(int status, int row);
     void selectSignal(QString uuid);
     void updateButton(int status, int row);
     void updateProjectStatus(QString uuid);
     void updateData(const QJsonObject &jsonObj);
+    void safeChecked(const QJsonObject &jsonObj);
     void countdown(QString uuid, const QString &topic, const QString &message);
     void closeFiring(QString uuid);
 
@@ -66,6 +70,7 @@ class firingWidget : public QWidget {
     void saveAndUploadRecord(const QJsonObject &jsonObj);
     void sendMqttMessage(const QString &topic, const QByteArray &message);
     void startBlasting();
+    void onSafeChecked(const QString projectUuid);
 
    private:
     Ui::firingWidget *ui;

+ 67 - 0
mainwindow.cpp

@@ -1,9 +1,13 @@
 #include "mainwindow.h"
 
+#include <QtCore/qlist.h>
+#include <QtCore/qobject.h>
+
 #include <QDebug>
 #include <QPushButton>
 #include <QWidget>
 
+#include "backendapimanager.h"
 #include "global.h"
 #include "jobs.h"
 #include "loadingWidget.h"
@@ -151,6 +155,26 @@ void MainWindow::messageAndTopicReceived(const QByteArray &message, const QMqttT
                     dao.updateBlastStatusByUuid(uuid, "2");
                 }
             }
+        } else if (jsonObj.contains("msgType") && jsonObj["msgType"].toString() == "safeCheck") {
+            // 处理安全验证消息
+            Logger::getInstance().info(QString("收到验证消息接收. message: ").arg(jsonObj));
+            if (jsonObj["status"] != "ok") {
+                QMessageBox::warning(this, "安全验证失败",
+                                     QString("安全验证未通过,练习安全员确认"));
+                return;
+            }
+
+            const QString addressUuid = jsonObj["addressUuid"].toString();
+            QJsonArray addressList = backendAPIManager::getHAddresses();
+
+            QList<QString> subAddressUuids = findAllChildUuids(addressList, addressUuid);
+            HProjectDao dao = HProjectDao(DatabaseManager::getInstance().getDatabase());
+
+            QList<QSharedPointer<HProject>> projects =
+                dao.getPendingSafeCheckProjByAddress(subAddressUuids);
+            // for (const auto &project : projects) {
+            //     emit firingWidget::safeChecked(project.getUuid());
+            // }
         }
     }
 }
@@ -230,3 +254,46 @@ void MainWindow::mouseMoveEvent(QMouseEvent *event) {
         event->accept();
     }
 }
+
+QList<QString> MainWindow::findAllChildUuids(const QJsonArray &addressArray,
+                                             const QString targetUuid) {
+    QList<QString> childrenUuids;
+
+    for (const QJsonValue &value : addressArray) {
+        if (!value.isObject()) continue;
+
+        QJsonObject addressObj = value.toObject();
+        QString currentUuid = addressObj["uuid"].toString();
+
+        if (currentUuid == targetUuid) {
+            // Found the target address, now collect all children UUIDs recursively
+            if (addressObj.contains("children") && addressObj["children"].isArray()) {
+                QJsonArray children = addressObj["children"].toArray();
+                for (const QJsonValue &child : children) {
+                    if (child.isObject()) {
+                        QString childUuid = child.toObject()["uuid"].toString();
+                        childrenUuids.append(childUuid);
+
+                        // Also add any grandchildren
+                        if (child.toObject().contains("children") &&
+                            child.toObject()["children"].isArray()) {
+                            QJsonArray grandchildren = child.toObject()["children"].toArray();
+                            childrenUuids.append(findAllChildUuids(
+                                grandchildren, child.toObject()["uuid"].toString()));
+                        }
+                    }
+                }
+                return childrenUuids;
+            }
+        } else if (addressObj.contains("children") && addressObj["children"].isArray()) {
+            // Continue searching in children
+            QJsonArray children = addressObj["children"].toArray();
+            QList<QString> result = findAllChildUuids(children, targetUuid);
+            if (!result.isEmpty()) {
+                return result;
+            }
+        }
+    }
+
+    return childrenUuids;
+}

+ 27 - 26
mainwindow.h

@@ -1,53 +1,55 @@
 #ifndef MAINWINDOW_H
 #define MAINWINDOW_H
 
+#include <QFrame>
+#include <QList>
 #include <QMainWindow>
 #include <QPropertyAnimation>
 #include <QPushButton>
-#include <QFrame>
-#include <QList>
 #include <QWidget>
-#include "mqtt/mqttclient.h"
+
 #include "addressfactory.h"
 #include "blastProject/blastprojectfactory.h"
-#include "equipmentfactory.h"
-#include "detInfo/detinfofactory.h"
-#include "blastoperationfactory.h"
 #include "blastRecord/blastrecordfactory.h"
+#include "blastoperationfactory.h"
+#include "detInfo/detinfofactory.h"
+#include "equipmentfactory.h"
+#include "global.h"
+#include "mqtt/mqttclient.h"
 #include "serial/serialtool.h"
 #include "serialGpsthread.h"
 #include "worker/timeupdatethread.h"
-#include "global.h"
-
 
 QT_BEGIN_NAMESPACE
-namespace Ui { class MainWindow; }
+namespace Ui {
+class MainWindow;
+}
 QT_END_NAMESPACE
 
-class MainWindow : public QMainWindow
-{
+class MainWindow : public QMainWindow {
     Q_OBJECT
 
-public:
+   public:
     MainWindow(QWidget *parent = nullptr);
     ~MainWindow();
 
     void setProjectTitle(const QString &newTitle);
 
-signals:
+   signals:
     void projectTitleChanged(const QString &newTitle);
 
-private slots:
+   private slots:
     void onToggleButtonClicked();
-    void onButtonClicked(QPushButton  *button);
+    void onButtonClicked(QPushButton *button);
     void handleStoredGNRMCData(const RMCData &data);
     void onTimeUpdated(const QString &timeString);
     void updateProjectTitleLabel(const QString &newTitle);
 
     void messageAndTopicReceived(const QByteArray &message, const QMqttTopicName &topic);
-private:
+
+   private:
     void initializeAnimate();
-    void setStyleSheets(QPushButton  *selectedButton);
+    void setStyleSheets(QPushButton *selectedButton);
     void switchPage(QWidget *button);
     void initialMqttService();
     void onMqttConnected();
@@ -55,25 +57,24 @@ private:
     void initialGPSSerial();
     void initDateTime();
     void onSerialToolCreated();
+    QList<QString> findAllChildUuids(const QJsonArray &addressArray, const QString targetUuid);
 
-
-private:
+   private:
     Ui::MainWindow *ui;
-    SerialTool* serialTool;
+    SerialTool *serialTool;
     bool m_isMqttConnected = false;
     bool m_btnSerialInitialized = false;
     QPropertyAnimation *animate_leftFrame;
-    QList<QWidget*> left_button_station;
-    QMap<QWidget*, PageFactory*> pageFactories;
-    QMap<QWidget*, QWidget*> createdPageByButton;
+    QList<QWidget *> left_button_station;
+    QMap<QWidget *, PageFactory *> pageFactories;
+    QMap<QWidget *, QWidget *> createdPageByButton;
     TimeUpdateThread *timeThread;
     QString lat = "未知";
     QString lon = "未知";
     QPoint m_dragPosition;
-    QString m_currentProjectTitle;    // Stores the current project title
-
+    QString m_currentProjectTitle;  // Stores the current project title
 
     void mousePressEvent(QMouseEvent *event);
     void mouseMoveEvent(QMouseEvent *event);
 };
-#endif // MAINWINDOW_H
+#endif  // MAINWINDOW_H