1
0

2 کامیت‌ها ac2bbba5a5 ... 93c5d087b3

نویسنده SHA1 پیام تاریخ
  Yao 93c5d087b3 dev: change operators into multiple selections 2 هفته پیش
  Yao 5e7d4d08e6 updates: db changes to sqllite 2 هفته پیش

+ 45 - 15
CMakeLists.txt

@@ -9,7 +9,7 @@ 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")
+set(CMAKE_PREFIX_PATH "C:/Qt/6.9.0/msvc2022_64")
 
 
 # # 设置 OpenSSL 安装路径
@@ -35,6 +35,7 @@ set(SOURCES
     blastopepage.cpp
     addressfactory.cpp
     addresspage.cpp
+    pagefactory.cpp
     components/MultiSelectComboBox.cpp
     blastProject/blastprojectfactory.cpp
     blastProject/blastprojectpage.cpp
@@ -51,6 +52,7 @@ set(SOURCES
     global.cpp
     httpclient.cpp
     jobs.cpp
+    logger.cpp
     login/loginwindow.cpp
     main.cpp
     mainwindow.cpp
@@ -66,6 +68,17 @@ set(SOURCES
     blastRegRecord/hblastregrecorddao.cpp
     fireWidget/firingwidget.cpp
     fireWidget/navprogress.cpp
+    des3encryption.cpp
+    countdownwidget.cpp
+    serial/serialtool.cpp
+    serial/serialgps.cpp
+    paregnrmc.cpp
+    serialgpsthread.cpp
+    worker/timeupdatethread.cpp
+    loadingWidget.cpp
+    backendapimanager.cpp
+    homepage.cpp
+    homepagefactory.cpp
 )
 
 # 定义头文件列表
@@ -75,6 +88,8 @@ set(HEADERS
     blastopepage.h
     addressfactory.h
     addresspage.h
+    pagefactory.h
+    components/MultiSelectComboBox.h
     blastProject/blastprojectfactory.h
     blastProject/blastprojectpage.h
     blastProject/hproject.h
@@ -90,6 +105,7 @@ set(HEADERS
     global.h
     httpclient.h
     jobs.h
+    logger.h
     login/loginwindow.h
     mainwindow.h
     registryManager/registrymanager.h
@@ -105,6 +121,16 @@ set(HEADERS
     blastRegRecord/hblastregrecorddao.h
     fireWidget/firingwidget.h
     fireWidget/navprogress.h
+    des3encryption.h
+    countdownwidget.h
+    serial/serialtool.h
+    serial/serialgps.h
+    paregnrmc.h
+    serialgpsthread.h
+    worker/timeupdatethread.h
+    loadingWidget.h
+    backendapimanager.h
+    homepage.h
 )
 
 # 定义 UI 文件列表
@@ -135,25 +161,29 @@ add_executable(${PROJECT_NAME}
     ${HEADERS}
     ${FORMS}
     ${RESOURCES}
-    des3encryption.h des3encryption.cpp
-    countdownwidget.h countdownwidget.cpp
-    serial/serialtool.h serial/serialtool.cpp
-    serial/serialgps.h serial/serialgps.cpp
-    paregnrmc.cpp paregnrmc.h
-    serialgpsthread.h serialgpsthread.cpp
-    worker/timeupdatethread.h worker/timeupdatethread.cpp
     logo.rc
-    logger.h
+)
+
+
+# 创建测试可执行文件
+add_executable(test_database
+    test_database.cpp
+    databasemanager.cpp
     logger.cpp
-    loadingWidget.h
-    loadingWidget.cpp
-    README.md
-    backendapimanager.h backendapimanager.cpp
+)
 
-    homepage.h homepage.cpp homepage.ui
-    homepagefactory.cpp
+# 链接测试可执行文件的库
+target_link_libraries(test_database
+    Qt${QT_VERSION_MAJOR}::Core
+    Qt${QT_VERSION_MAJOR}::Widgets
+    Qt${QT_VERSION_MAJOR}::Sql
+    ${OPENSSL_LIBRARIES}
 )
 
+# 设置测试可执行文件的输出目录
+set_target_properties(test_database PROPERTIES
+    RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
+)
 
 set_target_properties(${PROJECT_NAME} PROPERTIES
     WIN32_EXECUTABLE FALSE

+ 0 - 110
QframeTest01.pro

@@ -1,110 +0,0 @@
-QT       += core gui sql network
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-CONFIG += c++17
-
-# You can make your code fail to compile if it uses deprecated APIs.
-# In order to do so, uncomment the following line.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
-
-SOURCES += \
-    PageWidget.cpp \
-    addressfactory.cpp \
-    addresspage.cpp \
-    blastplanpage.cpp \
-    blastplanpfactory.cpp \
-    blastprojectfactory.cpp \
-    blastprojectpage.cpp \
-    book.cpp \
-    buttondelegate.cpp \
-    databasemanager.cpp \
-    detInfo/detinfofactory.cpp \
-    detInfo/detinfopage.cpp \
-    detdialog.cpp \
-    dialog.cpp \
-    equipment/equipmentfactory.cpp \
-    equipment/equipmentpage.cpp \
-    global.cpp \
-    hplan.cpp \
-    hplandao.cpp \
-    hproject.cpp \
-    hprojectdao.cpp \
-    httpclient.cpp \
-    jobs.cpp \
-    loginwindow.cpp \
-    main.cpp \
-    mainwindow.cpp \
-    mqtt/mqttclient.cpp \
-    newpagefactory.cpp \
-    page.cpp \
-    pagetest.cpp \
-    pagetestfactory.cpp \
-    plandialog.cpp \
-    projectdialog.cpp \
-    sysapi.cpp \
-    sysapidao.cpp \
-    testdialog.cpp
-
-HEADERS += \
-    PageWidget.h \
-    addressfactory.h \
-    addresspage.h \
-    blastplanpage.h \
-    blastplanpfactory.h \
-    blastprojectfactory.h \
-    blastprojectpage.h \
-    book.h \
-    buttondelegate.h \
-    databasemanager.h \
-    detInfo/detinfofactory.h \
-    detInfo/detinfopage.h \
-    detdialog.h \
-    dialog.h \
-    equipment/equipmentfactory.h \
-    equipment/equipmentpage.h \
-    global.h \
-    hplan.h \
-    hplandao.h \
-    hproject.h \
-    hprojectdao.h \
-    httpclient.h \
-    jobs.h \
-    loginwindow.h \
-    mainwindow.h \
-    PageFactory.h\
-    mqtt/mqttclient.h \
-    newpagefactory.h \
-    page.h \
-    pagetest.h \
-    pagetestfactory.h \
-    plandialog.h \
-    projectdialog.h \
-    regex.h \
-    sysapi.h \
-    sysapidao.h \
-    testdialog.h
-
-FORMS += \
-    PageWidget.ui \
-    addresspage.ui \
-    blastplanpage.ui \
-    blastprojectpage.ui \
-    detInfo/detinfopage.ui \
-    detdialog.ui \
-    dialog.ui \
-    equipment/equipmentpage.ui \
-    loginwindow.ui \
-    mainwindow.ui \
-    page.ui \
-    pagetest.ui \
-    plandialog.ui \
-    projectdialog.ui \
-    testdialog.ui
-# Default rules for deployment.
-qnx: target.path = /tmp/$${TARGET}/bin
-else: unix:!android: target.path = /opt/$${TARGET}/bin
-!isEmpty(target.path): INSTALLS += target
-QMAKE_PROJECT_DEPTH = 0
-RESOURCES += \
-    media.qrc

+ 41 - 39
blastProject/blastprojectpage.cpp

@@ -23,7 +23,7 @@ BlastProjectPage::BlastProjectPage(QWidget *parent)
     pageSize = 10;
     currentPage = 1;
 
-    dialog = new ProjectDialog(this);
+    m_dialog = new ProjectDialog(this);
     QJsonArray pcs = backendAPIManager::getHAddresses();
     addressOptions(pcs);
 
@@ -36,19 +36,20 @@ BlastProjectPage::BlastProjectPage(QWidget *parent)
     }
     initUserAndDialogOptions(allUsers);
 
-    connect(dialog, &ProjectDialog::createProject, this, &BlastProjectPage::createProject);
-    connect(dialog, &ProjectDialog::saveProject, this, &BlastProjectPage::updateProject);
+    connect(m_dialog, &ProjectDialog::createProject, this, &BlastProjectPage::createProject);
+    connect(m_dialog, &ProjectDialog::saveProject, this, &BlastProjectPage::updateProject);
 
-    RefreshData();
+    refreshData();
 }
 
-void BlastProjectPage::RefreshData() {
+void BlastProjectPage::refreshData() {
     loadDataFromSource(currentPage, pageSize);
     publishAllPendingBlastProjects();
 }
 
 void BlastProjectPage::loadDataFromSource(int currentPage, int pageSize) {
     PaginatedHProjectResult result = dao.getAllHProjects(currentPage, pageSize);
+    qDebug() << "loadDataFromSource: currentPage=" << currentPage << ", pageSize=" << pageSize << result.totalCount;
 
     QList<QSharedPointer<HProject>> projectList = result.projects;
 
@@ -113,7 +114,6 @@ void BlastProjectPage::loadDataFromSource(int currentPage, int pageSize) {
                     }
                 } else if (QStringList({"safetyInspectorIdentity", "operatorIdentity", "blasterIdentity"})
                                .contains(prop)) {
-                    qDebug() << "prop" << prop << value.toString().split(",");
                     item = new QStandardItem(getUserNameByIds(value.toString().split(",")));
                 } else {
                     item = new QStandardItem(value.toString());
@@ -186,30 +186,16 @@ void BlastProjectPage::initUserAndDialogOptions(const QJsonArray &dataArray) {
         }
     }
 
-    dialog->initComboBoxBlaster(blasterDeployerArray);
-    dialog->initComboBoxOperator(operatorArray);
-    dialog->initComboBoxSafetyInspectors(safeGuardArray);
+    m_dialog->initComboBoxBlaster(blasterDeployerArray);
+    m_dialog->initComboBoxOperator(operatorArray);
+    m_dialog->initComboBoxSafetyInspectors(safeGuardArray);
 }
 
 void BlastProjectPage::addressOptions(const QJsonArray &dataArrayAddress) {
-    dialog->SetL1AddressOptions(dataArrayAddress);
+    m_dialog->SetL1AddressOptions(dataArrayAddress);
     // dialog->setChildOptions(dataArrayAddress);
 }
 
-void BlastProjectPage::extractNames(const QJsonArray &array, QStringList &names) {
-    for (const auto &item : array) {
-        if (item.isObject()) {
-            QJsonObject obj = item.toObject();
-            if (obj.contains("name")) {
-                names.append(obj["name"].toString());
-            }
-            if (obj.contains("children") && obj["children"].isArray()) {
-                extractNames(obj["children"].toArray(), names);
-            }
-        }
-    }
-}
-
 void BlastProjectPage::parseJsonString(const QJsonDocument &jsonDoc) {
     QJsonObject jsonObj = jsonDoc.object();
     QJsonObject dataObj = jsonObj["data"].toObject();
@@ -217,16 +203,15 @@ void BlastProjectPage::parseJsonString(const QJsonDocument &jsonDoc) {
 }
 
 void BlastProjectPage::on_pushButton_clicked() {
-    dialog->setModal(false);
-    dialog->clearFormData();
-    dialog->setOperationType(0);
-    int ref = dialog->exec();
+    m_dialog->setModal(false);
+    m_dialog->clearFormData();
+    m_dialog->setOperationType(0);
+    int ref = m_dialog->exec();
     if (ref == QDialog::Accepted) {};
 }
 
 void BlastProjectPage::createProject(const QMap<QString, QString> &data) {
     HProject project;
-    qDebug() << "xxx: " << data.value("safetyInspectorIdentity");
     project.setName(data.value("name"));
     project.setDetSum(data.value("detNum"));
     project.setAddressUuid(data.value("addressUuid"));
@@ -243,19 +228,36 @@ void BlastProjectPage::createProject(const QMap<QString, QString> &data) {
     project.setUuid(QUuid::createUuid().toString(QUuid::WithoutBraces).remove(QRegularExpression("-")));
     project.setCreatedAt(QDateTime::currentDateTime());
     if (dao.addHProject(project)) {
-        RefreshData();
+        refreshData();
         publishAllPendingBlastProjects();
     }
 }
 
+QJsonArray BlastProjectPage::getUserInfoByIds(const QStringList &userIds) {
+    QJsonArray userInfoArray;
+    for (const QString &userId : userIds) {
+        if (m_userNameById.contains(userId)) {
+            QJsonObject userInfo;
+            userInfo["name"] = m_userNameById[userId];
+            userInfo["identity"] = userId;
+            userInfoArray.append(userInfo);
+        } else {
+            QMessageBox::critical(this, "错误", QString("用户(身份证: %1)不存在").arg(userId));
+        }
+    }
+    return userInfoArray;
+}
+
 void BlastProjectPage::publishAllPendingBlastProjects() {
     QJsonArray jsonArray;
     QList<QSharedPointer<HProject>> projectsReg = dao.getAllHProjectsReg();
     for (const auto &projectPtr : projectsReg) {
         if (projectPtr) {
-            QByteArray projectJson = projectPtr->ProjectToJson(*projectPtr);
-            QJsonDocument doc = QJsonDocument::fromJson(projectJson);
-            jsonArray.append(doc.object());
+            QJsonObject projectJson = projectPtr->ProjectToJson(*projectPtr);
+            projectJson["underground_blasters"] = getUserInfoByIds(projectPtr->getBlasterIdentity().split(","));
+            projectJson["ground_blasters"] = getUserInfoByIds(projectPtr->getOperatorIdentity().split(","));
+            projectJson["safety_inspectors"] = getUserInfoByIds(projectPtr->getSafetyInspectorIdentity().split(","));
+            jsonArray.append(projectJson);
         }
     }
 
@@ -266,10 +268,10 @@ void BlastProjectPage::publishAllPendingBlastProjects() {
 };
 
 void BlastProjectPage::updateButtonClicked(const HProject &project) {
-    dialog->setModal(false);
-    dialog->setOperationType(1);
-    dialog->setFormData(project);
-    int ref = dialog->exec();
+    m_dialog->setModal(false);
+    m_dialog->setOperationType(1);
+    m_dialog->setFormData(project);
+    int ref = m_dialog->exec();
     if (ref == QDialog::Accepted) {};
 }
 
@@ -283,13 +285,13 @@ void BlastProjectPage::updateProject(const QMap<QString, QString> &data) {
     project.setOperatorIdentity(data.value("operatorIdentity"));
     project.setUpdatedAt(QDateTime::currentDateTime());
     if (dao.updateHProject(project)) {
-        RefreshData();
+        refreshData();
         publishAllPendingBlastProjects();
     }
 }
 void BlastProjectPage::deleteButtonClicked(const HProject &project) {
     if (dao.deleteHProject(project)) {
-        RefreshData();
+        refreshData();
         publishAllPendingBlastProjects();
     }
 }

+ 3 - 3
blastProject/blastprojectpage.h

@@ -32,7 +32,7 @@ class BlastProjectPage : public QWidget {
     void updateProjectUUId(QString uuid);
 
    private:
-    void RefreshData();
+    void refreshData();
     void loadDataFromSource(int currentPage, int pageSize);
     void initUserAndDialogOptions(const QJsonArray &arrayData);
     void addressOptions(const QJsonArray &jsonArray);
@@ -42,13 +42,12 @@ class BlastProjectPage : public QWidget {
     void updateButtonClicked(const HProject &project);
     void updateProject(const QMap<QString, QString> &data);
     void deleteButtonClicked(const HProject &project);
-    void extractNames(const QJsonArray &array, QStringList &names);
     void publishAllPendingBlastProjects();
 
    private:
     Ui::BlastProjectPage *ui;
     PageWidget *pageWidget;
-    ProjectDialog *dialog;
+    ProjectDialog *m_dialog;
     HttpClient *m_httpClient;
     HProjectDao dao;
     QJsonArray dataArray;
@@ -59,6 +58,7 @@ class BlastProjectPage : public QWidget {
     int totalCount;
     int updateId;
     QString getUserNameByIds(const QStringList &userIds);
+    QJsonArray getUserInfoByIds(const QStringList &userIds);
 };
 
 #endif  // BLASTPROJECTPAGE_H

+ 4 - 7
blastProject/hproject.cpp

@@ -49,10 +49,6 @@ QString HProject::getAddressPath() const { return addressPath; }
 
 void HProject::setAddressPath(const QString &newAddressPath) { addressPath = newAddressPath; }
 
-QString HProject::getPcSn() const { return pcSn; }
-
-void HProject::setPcSn(const QString &newPcSn) { pcSn = newPcSn; }
-
 QString HProject::getDetSum() const { return detSum; }
 
 void HProject::setDetSum(const QString &newDetSum) { detSum = newDetSum; }
@@ -97,8 +93,9 @@ QString HProject::getLevel4Address() const { return level4Address; }
 
 void HProject::setLevel4Address(const QString &newLevel4Address) { level4Address = newLevel4Address; }
 
-QByteArray HProject::ProjectToJson(const HProject &project) {
+QJsonObject HProject::ProjectToJson(const HProject &project) {
     QJsonObject jsonObject;
+
     jsonObject["name"] = project.getName();
     jsonObject["uuid"] = project.getUuid();
     jsonObject["xmbh"] = project.getXmbh();
@@ -111,6 +108,6 @@ QByteArray HProject::ProjectToJson(const HProject &project) {
     jsonObject["safetyInspectorIdentity"] = project.getSafetyInspectorIdentity();
     jsonObject["level4Address"] = project.getLevel4Address();
     jsonObject["blastCount"] = project.getBlastCount();
-    QJsonDocument jsonDoc(jsonObject);
-    return jsonDoc.toJson(QJsonDocument::Compact);
+
+    return jsonObject;
 }

+ 1 - 5
blastProject/hproject.h

@@ -28,7 +28,6 @@ class HProject : public QObject {
     Q_PROPERTY(QString addressUuid READ getAddressUuid WRITE setAddressUuid)
     Q_PROPERTY(QString addressPath READ getAddressPath WRITE setAddressPath)
     Q_PROPERTY(QString level4Address READ getLevel4Address WRITE setLevel4Address)
-    Q_PROPERTY(QString pcSn READ getPcSn WRITE setPcSn)
     Q_PROPERTY(QString detSum READ getDetSum WRITE setDetSum)
     Q_PROPERTY(QString blastCount READ getBlastCount WRITE setBlastCount)
     Q_PROPERTY(QString fileName READ getFileName WRITE setFileName)
@@ -74,9 +73,6 @@ class HProject : public QObject {
     QString getAddressPath() const;
     void setAddressPath(const QString &newAddressPath);
 
-    QString getPcSn() const;
-    void setPcSn(const QString &newPcSn);
-
     QString getDetSum() const;
     void setDetSum(const QString &newDetSum);
 
@@ -104,7 +100,7 @@ class HProject : public QObject {
     qint64 getUpdateBy() const;
     void setUpdateBy(qint64 newUpdateBy);
 
-    QByteArray ProjectToJson(const HProject &project);
+    QJsonObject ProjectToJson(const HProject &project);
 
     QString getBlastCount() const;
     void setBlastCount(const QString &newBlastCount);

+ 6 - 9
blastProject/hprojectdao.cpp

@@ -7,12 +7,12 @@ HProjectDao::HProjectDao(QSqlDatabase db) : database(db) {}
 bool HProjectDao::addHProject(const HProject &project) {
     QSqlQuery query;
     query.prepare(
-        "INSERT INTO h_project (uuid, name, company_code, htid, xmbh,  "
+        "INSERT INTO h_project (uuid, name, company_code, htid, xmbh, "
         "operator_identity, blaster_identity, safety_inspector_identity, address_uuid, address_path, "
-        "level4_address,pc_sn,det_sum, file_name, file_url, blast_status,blast_count,created_at, updated_at, "
+        "level4_address, 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, :operatorIdentity, "
-        ":blasterIdentity, :safetyInspectorIdentity, :addressUuid, :addressPath, :level4Address, :pcSn, :detSum, "
+        ":blasterIdentity, :safetyInspectorIdentity, :addressUuid, :addressPath, :level4Address, :detSum, "
         ":fileName, :fileUrl, :blastStatus, :blastCount,:createdAt, :updatedAt, :deletedAt, :createBy, :updateBy)");
 
     query.bindValue(":uuid", project.getUuid());
@@ -26,15 +26,14 @@ bool HProjectDao::addHProject(const HProject &project) {
     query.bindValue(":addressUuid", project.getAddressUuid());
     query.bindValue(":addressPath", project.getAddressPath());
     query.bindValue(":level4Address", project.getLevel4Address());
-    query.bindValue(":blastCount", project.getBlastCount());
-    query.bindValue(":pcSn", project.getPcSn());
     query.bindValue(":detSum", project.getDetSum());
     query.bindValue(":fileName", project.getFileName());
     query.bindValue(":fileUrl", project.getFileUrl());
     query.bindValue(":blastStatus", project.getBlastStatus());
+    query.bindValue(":blastCount", project.getBlastCount());
     query.bindValue(":createdAt", project.getCreatedAt().toString(Qt::ISODateWithMs));
     query.bindValue(":updatedAt", project.getUpdatedAt().toString(Qt::ISODateWithMs));
-    query.bindValue(":deletedAt", project.getDeletedAt().toString(Qt::ISODateWithMs));
+    query.bindValue(":deletedAt", QVariant(QVariant::String)); // 这里可以设置为NULL或当前时间
     query.bindValue(":createBy", project.getCreateBy());
     query.bindValue(":updateBy", project.getUpdateBy());
     if (!query.exec()) {
@@ -59,7 +58,6 @@ bool HProjectDao::updateHProject(const HProject &project) {
         "safetyInspector_identity = :safetyInspectorIdentity, "
         "address_uuid = :addressUuid, "
         "address_path = :addressPath, "
-        "pc_sn = :pcSn, "
         "det_sum = :detSum, "
         "file_name = :fileName, "
         "file_url = :fileUrl, "
@@ -82,7 +80,6 @@ bool HProjectDao::updateHProject(const HProject &project) {
     query.bindValue(":safetyInspectorIdentity", project.getSafetyInspectorIdentity());
     query.bindValue(":addressUuid", project.getAddressUuid());
     query.bindValue(":addressPath", project.getAddressPath());
-    query.bindValue(":pcSn", project.getPcSn());
     query.bindValue(":detSum", project.getDetSum());
     query.bindValue(":fileName", project.getFileName());
     query.bindValue(":fileUrl", project.getFileUrl());
@@ -262,7 +259,7 @@ QSharedPointer<HProject> HProjectDao::recordToProject(const QSqlRecord &record)
     project->setSafetyInspectorIdentity(record.value("safety_inspector_identity").toString());
     project->setAddressUuid(record.value("address_uuid").toString());
     project->setAddressPath(record.value("address_path").toString());
-    project->setPcSn(record.value("pc_sn").toString());
+    project->setLevel4Address(record.value("level4_address").toString());
     project->setDetSum(record.value("det_sum").toString());
     project->setBlastCount(record.value("blast_count").toString());
     project->setFileName(record.value("file_name").toString());

+ 10 - 28
blastProject/projectdialog.cpp

@@ -9,6 +9,7 @@
 
 #include "../components/MultiSelectComboBox.h"
 #include "ui_projectdialog.h"
+#include "../logger.h"
 
 ProjectDialog::ProjectDialog(QWidget *parent) : QDialog(parent), ui(new Ui::ProjectDialog) {
     ui->setupUi(this);
@@ -92,20 +93,6 @@ void ProjectDialog::updateL3AddressOptions() {
 
 void ProjectDialog::setChildOptions(const QJsonArray &newDataOptions) { dataOptions = newDataOptions; }
 
-void ProjectDialog::extractNames(const QJsonArray &array, QStringList &names) {
-    for (const auto &item : array) {
-        if (item.isObject()) {
-            QJsonObject obj = item.toObject();
-            if (obj.contains("name")) {
-                names.append(obj["name"].toString());
-            }
-            if (obj.contains("children") && obj["children"].isArray()) {
-                extractNames(obj["children"].toArray(), names);
-            }
-        }
-    }
-}
-
 void ProjectDialog::clearFormData() {
     QList<QLineEdit *> lineEdits = findChildren<QLineEdit *>();
     for (QLineEdit *lineEdit : lineEdits) {
@@ -147,16 +134,12 @@ void ProjectDialog::validateAndSaveProject() {
     for (const auto &pair :
          ui->undergroundOperatorsWidget->findChild<MultiSelectComboBox *>()->checkedItemsWithKeys()) {
         selectedBlasters.append(pair.first);
-        qDebug() << "Selected underground operator:" << pair.first;
     }
     for (const auto &pair : ui->groundOperatorsWidget->findChild<MultiSelectComboBox *>()->checkedItemsWithKeys()) {
         selectedOperators.append(pair.first);
-        qDebug() << "Selected ground operator:" << pair.first;
     }
     for (const auto &pair : ui->safetyInspectorsWidget->findChild<MultiSelectComboBox *>()->checkedItemsWithKeys()) {
         selectedSafetyInspectors.append(pair.first);
-
-        qDebug() << "Selected safety inspector:" << pair.first;
     }
 
     QString detNum = ui->editDetNum->text().trimmed();
@@ -241,7 +224,12 @@ void ProjectDialog::setFormData(const HProject &Project) {
         ui->editRegCount->setText(Project.getBlastCount());
         ui->level4Address->setText(Project.getLevel4Address());
 
-        // TODO: 这里需要处理井下爆破员和井上爆破员及安全员
+        ui->groundOperatorsWidget->findChild<MultiSelectComboBox *>()->setCheckedKeys(
+            Project.getOperatorIdentity().split(","));
+        ui->undergroundOperatorsWidget->findChild<MultiSelectComboBox *>()->setCheckedKeys(
+            Project.getBlasterIdentity().split(","));
+        ui->safetyInspectorsWidget->findChild<MultiSelectComboBox *>()->setCheckedKeys(
+            Project.getSafetyInspectorIdentity().split(","));
 
         // 设置地址选择
         QStringList addressParts = Project.getAddressPath().split("/");
@@ -256,9 +244,7 @@ void ProjectDialog::setFormData(const HProject &Project) {
         if (indexAddr != -1) {
             // 如果找到了对应的索引,设置为当前索引
             ui->comboBoxAddr->setCurrentIndex(indexAddr);
-            qDebug() << "已将选项 " << addressVariables[0] << " 设置为当前显示的选项。";
         } else {
-            // 如果没找到,输出提示信息
             qDebug() << "未找到选项 " << addressVariables[0];
         }
         if (addressVariables.size() >= 2) {
@@ -267,9 +253,7 @@ void ProjectDialog::setFormData(const HProject &Project) {
             if (indexAddr_2 != -1) {
                 // 如果找到了对应的索引,设置为当前索引
                 ui->comboBoxAddr_2->setCurrentIndex(indexAddr_2);
-                qDebug() << "已将选项 " << addressVariables[1] << " 设置为当前显示的选项。";
             } else {
-                // 如果没找到,输出提示信息
                 qDebug() << "未找到选项 " << addressVariables[1];
             }
         }
@@ -280,16 +264,14 @@ void ProjectDialog::setFormData(const HProject &Project) {
             if (indexAddr_3 != -1) {
                 // 如果找到了对应的索引,设置为当前索引
                 ui->comboBoxAddr_3->setCurrentIndex(indexAddr_3);
-                qDebug() << "已将选项 " << addressVariables[2] << " 设置为当前显示的选项。";
             } else {
                 // 如果没找到,输出提示信息
                 qDebug() << "未找到选项 " << addressVariables[2];
             }
         }
-    } catch (const std::exception &e) {
-        qDebug() << "发生异常: " << e.what();
-    } catch (...) {
-        qDebug() << "发生未知异常";
+    } catch (const std::exception& e) {
+        Logger::getInstance().error(QString("设置表单数据时发生异常: %1").arg(e.what()));
+        QMessageBox::warning(this, "错误", "无法设置表单数据,请检查数据格式是否正确。");
     }
 }
 

+ 0 - 1
blastProject/projectdialog.h

@@ -43,7 +43,6 @@ class ProjectDialog : public QDialog {
     void updateL2AddressOptions();
     void updateL3AddressOptions();
     void validateAndSaveProject();
-    void extractNames(const QJsonArray &array, QStringList &names);
 
    private:
     Ui::ProjectDialog *ui;

+ 58 - 2
components/MultiSelectComboBox.cpp

@@ -3,6 +3,7 @@
 #include <QDebug>
 #include <QEvent>
 #include <QLineEdit>
+#include <QMouseEvent>
 #include <QStandardItem>
 #include <QStandardItemModel>
 #include <QStyleOptionComboBox>
@@ -20,13 +21,18 @@ void MultiSelectComboBox::initialize() {
     QListView *listView = new QListView(this);
     setView(listView);
 
-    // Make the combo box read-only
+    // Make the combo box read-only but clickable
     setEditable(true);
     setInsertPolicy(QComboBox::NoInsert);
     lineEdit()->setReadOnly(true);
 
+    // 设置输入框样式,使其看起来可点击
+    lineEdit()->setCursor(Qt::PointingHandCursor);
+    lineEdit()->setStyleSheet("QLineEdit { background-color: white; }");
+
     // Install event filter to handle mouse events
     view()->viewport()->installEventFilter(this);
+    lineEdit()->installEventFilter(this);
 
     // Connect to the item changed signal
     connect(model(), &QStandardItemModel::itemChanged, this, &MultiSelectComboBox::onItemChanged);
@@ -87,11 +93,45 @@ void MultiSelectComboBox::setCheckedKeys(const QStringList &keys) {
 
 bool MultiSelectComboBox::eventFilter(QObject *object, QEvent *event) {
     if (object == view()->viewport()) {
+        if (event->type() == QEvent::MouseButtonPress) {
+            QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
+            if (mouseEvent->button() == Qt::LeftButton) {
+                QModelIndex index = view()->indexAt(mouseEvent->pos());
+                if (index.isValid()) {
+                    // 切换选中状态
+                    QStandardItem *item = model()->itemFromIndex(index);
+                    if (item) {
+                        Qt::CheckState currentState =
+                            static_cast<Qt::CheckState>(item->data(Qt::CheckStateRole).toInt());
+                        Qt::CheckState newState = (currentState == Qt::Checked) ? Qt::Unchecked : Qt::Checked;
+                        item->setData(newState, Qt::CheckStateRole);
+
+                        // 防止点击选项后立即关闭弹出菜单
+                        skipNextHide = true;
+                        return true;  // 阻止默认处理
+                    }
+                }
+            }
+        }
         if (event->type() == QEvent::MouseButtonRelease) {
+            // 防止点击选项后立即关闭弹出菜单
             skipNextHide = true;
+            return false;
+        }
+    } else if (object == lineEdit()) {
+        if (event->type() == QEvent::MouseButtonPress) {
+            QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
+            if (mouseEvent->button() == Qt::LeftButton) {
+                if (!view()->isVisible()) {
+                    showPopup();
+                } else {
+                    hidePopup();
+                }
+                return true;  // 事件已处理
+            }
         }
     }
-    return false;
+    return QComboBox::eventFilter(object, event);
 }
 
 void MultiSelectComboBox::showPopup() { QComboBox::showPopup(); }
@@ -104,6 +144,22 @@ void MultiSelectComboBox::hidePopup() {
     QComboBox::hidePopup();
 }
 
+void MultiSelectComboBox::mousePressEvent(QMouseEvent *event) {
+    // 如果点击的是输入框区域,显示弹出菜单
+    if (event->button() == Qt::LeftButton) {
+        if (!view()->isVisible()) {
+            showPopup();
+        } else {
+            hidePopup();
+        }
+        event->accept();
+        return;
+    }
+
+    // 其他情况调用父类方法
+    QComboBox::mousePressEvent(event);
+}
+
 void MultiSelectComboBox::onItemChanged(QStandardItem *item) {
     Q_UNUSED(item);
     updateText();

+ 1 - 0
components/MultiSelectComboBox.h

@@ -28,6 +28,7 @@ class MultiSelectComboBox : public QComboBox {
     void showPopup() override;
     void hidePopup() override;
     void paintEvent(QPaintEvent *event) override;
+    void mousePressEvent(QMouseEvent *event) override;
 
    private slots:
     void onItemChanged(QStandardItem *item);

+ 76 - 14
databasemanager.cpp

@@ -1,8 +1,11 @@
 #include "databasemanager.h"
 
 #include <QDebug>
+#include <QDir>
 #include <QMessageBox>
 #include <QSqlError>
+#include <QSqlQuery>
+#include <QStandardPaths>
 
 #include "global.h"
 #include "logger.h"
@@ -13,21 +16,36 @@ DatabaseManager& DatabaseManager::getInstance() {
 }
 
 // 创建一个新的数据库连接
-DatabaseManager::DatabaseManager() : db(QSqlDatabase::addDatabase("QMYSQL")) {
-    db.setHostName(databaseHost);
-    db.setDatabaseName("pc_system");
-    db.setUserName("root");
-    db.setPassword("123456");
-
-    if (!db.open()) {
-        Logger::getInstance().error(
-            QString("Mysql Connected error. host: %1, error: %2").arg(databaseHost, db.lastError().text()));
-        QMessageBox::critical(nullptr, "错误",
-                              QString("无法连接数据库, 请联系开发人员。\n 错误: %1").arg(db.lastError().text()));
-
-        throw std::runtime_error("Database connection failed: " + db.lastError().text().toStdString());
+DatabaseManager::DatabaseManager() : db(QSqlDatabase::addDatabase("QSQLITE")) {
+    // 设置SQLite数据库文件路径
+    QString appDataPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
+    QDir appDataDir(appDataPath);
+    if (!appDataDir.exists()) {
+        appDataDir.mkpath(".");
+    }
+
+    QString dbPath = appDataPath + "/smartmine.db";
+    qDebug() << "Database path:" << dbPath;
+    db.setDatabaseName(dbPath);
+
+    try {
+        if (!db.open()) {
+            Logger::getInstance().error(
+                QString("SQLite Connected error. path: %1, error: %2").arg(dbPath, db.lastError().text()));
+            QMessageBox::critical(nullptr, "错误",
+                                  QString("无法连接数据库, 请联系开发人员。\n 错误: %1").arg(db.lastError().text()));
+
+            throw std::runtime_error("Database connection failed: " + db.lastError().text().toStdString());
+        }
+
+        Logger::getInstance().info(QString("SQLite Connected. path: %1").arg(dbPath));
+
+        // 初始化数据库表结构
+        initializeTables();
+    } catch (const std::exception& e) {
+        Logger::getInstance().error(QString("Database initialization failed: %1").arg(e.what()));
+        QMessageBox::critical(nullptr, "错误", QString("数据库初始化失败: %1").arg(e.what()));
     }
-    Logger::getInstance().info(QString("Mysql Connected. host: %1").arg(databaseHost));
 }
 
 DatabaseManager::~DatabaseManager() {
@@ -37,3 +55,47 @@ DatabaseManager::~DatabaseManager() {
 }
 
 QSqlDatabase& DatabaseManager::getDatabase() { return db; }
+
+void DatabaseManager::initializeTables() {
+    QSqlQuery query(db);
+
+    // 创建 h_project 表 (SQLite语法,基于提供的MySQL结构)
+    QString createHProjectTable = R"(
+        CREATE TABLE IF NOT EXISTS h_project (
+            id INTEGER PRIMARY KEY AUTOINCREMENT,
+            uuid TEXT,
+            name TEXT,
+            company_code TEXT,
+            htid TEXT,
+            xmbh TEXT,
+            operator_identity TEXT,
+            safety_inspector_identity TEXT,
+            blaster_identity TEXT,
+            blast_count TEXT,
+            address_path TEXT,
+            level4_address TEXT,
+            address_uuid TEXT,
+            det_sum TEXT,
+            file_name TEXT,
+            file_url TEXT,
+            blast_status TEXT,
+            created_at TEXT,
+            updated_at TEXT,
+            deleted_at TEXT,
+            create_by INTEGER,
+            update_by INTEGER
+        )
+    )";
+
+    if (!query.exec(createHProjectTable)) {
+        Logger::getInstance().error(QString("Failed to create h_project table: %1").arg(query.lastError().text()));
+        throw std::runtime_error("Failed to create h_project table");
+    }
+
+    // 创建索引(可选,提高查询性能)
+    query.exec("CREATE INDEX IF NOT EXISTS idx_h_project_uuid ON h_project(uuid)");
+    query.exec("CREATE INDEX IF NOT EXISTS idx_h_project_blast_status ON h_project(blast_status)");
+    query.exec("CREATE INDEX IF NOT EXISTS idx_h_project_deletion_date ON h_project(deletion_date)");
+
+    Logger::getInstance().info("Database tables initialized successfully");
+}

+ 1 - 0
databasemanager.h

@@ -12,6 +12,7 @@ class DatabaseManager {
     ~DatabaseManager();
     DatabaseManager(const DatabaseManager&) = delete;
     DatabaseManager& operator=(const DatabaseManager&) = delete;
+    void initializeTables();  // 初始化数据库表结构
     QSqlDatabase db;
 };
 

+ 0 - 93
home.ui.autosave

@@ -1,93 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>Form</class>
- <widget class="QWidget" name="Form">
-  <property name="geometry">
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>890</width>
-    <height>422</height>
-   </rect>
-  </property>
-  <property name="windowTitle">
-   <string>Form</string>
-  </property>
-  <widget class="QWidget" name="verticalLayoutWidget">
-   <property name="geometry">
-    <rect>
-     <x>9</x>
-     <y>9</y>
-     <width>871</width>
-     <height>71</height>
-    </rect>
-   </property>
-   <layout class="QVBoxLayout" name="verticalLayout"/>
-  </widget>
-  <widget class="QWidget" name="gridLayoutWidget">
-   <property name="geometry">
-    <rect>
-     <x>30</x>
-     <y>90</y>
-     <width>411</width>
-     <height>80</height>
-    </rect>
-   </property>
-   <layout class="QGridLayout" name="gridLayout"/>
-  </widget>
-  <widget class="QWidget" name="verticalLayoutWidget_2">
-   <property name="geometry">
-    <rect>
-     <x>440</x>
-     <y>90</y>
-     <width>411</width>
-     <height>81</height>
-    </rect>
-   </property>
-   <layout class="QVBoxLayout" name="verticalLayout_2">
-    <item>
-     <widget class="QLCDNumber" name="todayBlastCout"/>
-    </item>
-   </layout>
-  </widget>
-  <widget class="QWidget" name="gridLayoutWidget_2">
-   <property name="geometry">
-    <rect>
-     <x>30</x>
-     <y>170</y>
-     <width>411</width>
-     <height>81</height>
-    </rect>
-   </property>
-   <layout class="QGridLayout" name="gridLayout_2">
-    <item row="0" column="0">
-     <widget class="QLabel" name="label_2">
-      <property name="text">
-       <string> 本周爆破量:</string>
-      </property>
-      <property name="margin">
-       <number>20</number>
-      </property>
-     </widget>
-    </item>
-   </layout>
-  </widget>
-  <widget class="QWidget" name="gridLayoutWidget_3">
-   <property name="geometry">
-    <rect>
-     <x>440</x>
-     <y>170</y>
-     <width>411</width>
-     <height>81</height>
-    </rect>
-   </property>
-   <layout class="QGridLayout" name="gridLayout_3">
-    <item row="1" column="0">
-     <widget class="QLCDNumber" name="lcdNumber"/>
-    </item>
-   </layout>
-  </widget>
- </widget>
- <resources/>
- <connections/>
-</ui>

+ 0 - 4
hproject.cpp

@@ -47,10 +47,6 @@ QString HProject::getAddressUuid() const { return addressUuid; }
 
 void HProject::setAddressUuid(const QString &newAddressUuid) { addressUuid = newAddressUuid; }
 
-QString HProject::getPcSn() const { return pcSn; }
-
-void HProject::setPcSn(const QString &newPcSn) { pcSn = newPcSn; }
-
 QString HProject::getDetSum() const { return detSum; }
 
 void HProject::setDetSum(const QString &newDetSum) { detSum = newDetSum; }

+ 0 - 4
hproject.h

@@ -21,7 +21,6 @@ class HProject : public QObject {
     Q_PROPERTY(QString blasterName READ getBlasterName WRITE setBlasterName)
     Q_PROPERTY(QString blasterIdentity READ getBlasterIdentity WRITE setBlasterIdentity)
     Q_PROPERTY(QString addressUuid READ getAddressUuid WRITE setAddressUuid)
-    Q_PROPERTY(QString pcSn READ getPcSn WRITE setPcSn)
     Q_PROPERTY(QString detSum READ getDetSum WRITE setDetSum)
     Q_PROPERTY(QString fileName READ getFileName WRITE setFileName)
     Q_PROPERTY(QString fileUrl READ getFileUrl WRITE setFileUrl)
@@ -69,9 +68,6 @@ class HProject : public QObject {
     QString getAddressUuid() const;
     void setAddressUuid(const QString &newAddressUuid);
 
-    QString getPcSn() const;
-    void setPcSn(const QString &newPcSn);
-
     QString getDetSum() const;
     void setDetSum(const QString &newDetSum);
 

+ 0 - 3
hprojectdao.cpp

@@ -21,7 +21,6 @@ bool HProjectDao::addHProject(const HProject &project) {
     query.bindValue(":blasterIdentity", project.getBlasterIdentity());
     query.bindValue(":safetyInspectorIdentity", project.getBlasterIdentity());
     query.bindValue(":addressUuid", project.getAddressUuid());
-    query.bindValue(":pcSn", project.getPcSn());
     query.bindValue(":detSum", project.getDetSum());
     query.bindValue(":fileName", project.getFileName());
     query.bindValue(":fileUrl", project.getFileUrl());
@@ -78,7 +77,6 @@ bool HProjectDao::updateHProject(const HProject &project) {
     query.bindValue(":blasterName", project.getBlasterName());
     query.bindValue(":blasterIdentity", project.getBlasterIdentity());
     query.bindValue(":addressUuid", project.getAddressUuid());
-    query.bindValue(":pcSn", project.getPcSn());
     query.bindValue(":detSum", project.getDetSum());
     query.bindValue(":fileName", project.getFileName());
     query.bindValue(":fileUrl", project.getFileUrl());
@@ -163,7 +161,6 @@ QSharedPointer<HProject> HProjectDao::recordToProject(const QSqlRecord &record)
     project->setBlasterName(record.value("blaster_name").toString());
     project->setBlasterIdentity(record.value("blaster_identity").toString());
     project->setAddressUuid(record.value("address_uuid").toString());
-    project->setPcSn(record.value("pc_sn").toString());
     project->setDetSum(record.value("det_sum").toString());
     project->setFileName(record.value("file_name").toString());
     project->setFileUrl(record.value("file_url").toString());

+ 15 - 14
mainwindow.cpp

@@ -150,22 +150,23 @@ void MainWindow::initialMqttService() {
 }
 
 void MainWindow::publishBlastProjects() {
-    QJsonArray jsonArray;
-    HProjectDao dao = HProjectDao(DatabaseManager::getInstance().getDatabase());
-
-    QList<QSharedPointer<HProject>> projectsReg = dao.getAllHProjectsReg();
-    for (const auto &projectPtr : projectsReg) {
-        if (projectPtr) {
-            QByteArray projectJson = projectPtr->ProjectToJson(*projectPtr);
-            QJsonDocument doc = QJsonDocument::fromJson(projectJson);
-            jsonArray.append(doc.object());
-        }
-    }
+    // TODO: publish by emit message
+    // QJsonArray jsonArray;
+    // HProjectDao dao = HProjectDao(DatabaseManager::getInstance().getDatabase());
+
+    // QList<QSharedPointer<HProject>> projectsReg = dao.getAllHProjectsReg();
+    // for (const auto &projectPtr : projectsReg) {
+    //     if (projectPtr) {
+    //         QByteArray projectJson = projectPtr->ProjectToJson(*projectPtr);
+    //         QJsonDocument doc = QJsonDocument::fromJson(projectJson);
+    //         jsonArray.append(doc.object());
+    //     }
+    // }
 
-    QJsonDocument jsonDoc(jsonArray);
-    QByteArray jsonData = jsonDoc.toJson(QJsonDocument::Indented);
+    // QJsonDocument jsonDoc(jsonArray);
+    // QByteArray jsonData = jsonDoc.toJson(QJsonDocument::Indented);
 
-    mainMqttClient->sendMessage(MQTT_TOPIC_COMPANY_PROJECTS_PUBLISH, jsonData, 2, true);
+    // mainMqttClient->sendMessage(MQTT_TOPIC_COMPANY_PROJECTS_PUBLISH, jsonData, 2, true);
 }
 
 void MainWindow::handleMqttProjectsMessage(const QMqttMessage &message) {

+ 73 - 0
test_database.cpp

@@ -0,0 +1,73 @@
+#include <QCoreApplication>
+#include <QDateTime>
+#include <QDebug>
+#include <QSqlDatabase>
+#include <QSqlError>
+#include <QSqlQuery>
+
+#include "databasemanager.h"
+#include "logger.h"
+
+int main(int argc, char* argv[]) {
+    QCoreApplication app(argc, argv);
+
+    try {
+        // 初始化数据库
+        DatabaseManager& dbManager = DatabaseManager::getInstance();
+        QSqlDatabase& db = dbManager.getDatabase();
+
+        qDebug() << "Database connected successfully!";
+        qDebug() << "Database file path:" << db.databaseName();
+
+        // 测试表是否创建成功
+        QSqlQuery query(db);
+
+        // 检查表是否存在
+        if (query.exec("SELECT name FROM sqlite_master WHERE type='table' AND name='h_project'")) {
+            if (query.next()) {
+                qDebug() << "Table h_project exists!";
+            } else {
+                qDebug() << "Table h_project does not exist!";
+            }
+        }
+
+        // 测试插入一条数据
+        query.prepare(R"(
+            INSERT INTO h_project (uuid, name, company_code, blast_status, created_at) 
+            VALUES (:uuid, :name, :company_code, :blast_status, :created_at)
+        )");
+
+        query.bindValue(":uuid", "test-uuid-123");
+        query.bindValue(":name", "Test Project");
+        query.bindValue(":company_code", "TEST001");
+        query.bindValue(":blast_status", "1");
+        query.bindValue(":created_at", QDateTime::currentDateTime().toString(Qt::ISODateWithMs));
+
+        if (query.exec()) {
+            qDebug() << "Test data inserted successfully!";
+        } else {
+            qDebug() << "Failed to insert test data:" << query.lastError().text();
+        }
+
+        // 测试查询数据
+        if (query.exec("SELECT uuid, name, company_code FROM h_project WHERE uuid = 'test-uuid-123'")) {
+            if (query.next()) {
+                qDebug() << "Test data retrieved:";
+                qDebug() << "  UUID:" << query.value("uuid").toString();
+                qDebug() << "  Name:" << query.value("name").toString();
+                qDebug() << "  Company Code:" << query.value("company_code").toString();
+            }
+        }
+
+        // 清理测试数据
+        query.exec("DELETE FROM h_project WHERE uuid = 'test-uuid-123'");
+
+        qDebug() << "Database migration test completed successfully!";
+
+    } catch (const std::exception& e) {
+        qDebug() << "Database error:" << e.what();
+        return 1;
+    }
+
+    return 0;
+}