diff --git a/.gitignore b/.gitignore index 30a4a93..aba7feb 100644 --- a/.gitignore +++ b/.gitignore @@ -69,3 +69,12 @@ LaunchRegisterKey.vcxproj.filters .vs/LaunchRegisterKey/v17/ipch/AutoPCH/e407f47aecf49074/UDPDATATHREAD.ipch debug/ release/ +.vs/ +LaunchRe.82F475D3.tlog/ +qmake/ +LaunchRegisterKey.log +LaunchRegisterKey.sln +qt_work.log +vc141.pdb +vcpkg.applocal.log +CMakeLists.txt diff --git a/LaunchRegisterKey.pro b/LaunchRegisterKey.pro index bc8c760..1907df6 100644 --- a/LaunchRegisterKey.pro +++ b/LaunchRegisterKey.pro @@ -1,9 +1,12 @@ +QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO +QMAKE_LFLAGS_RELEASE = $$QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO + QT += core gui network sql greaterThan(QT_MAJOR_VERSION, 4): QT += widgets CONFIG += c++11 - +RC_ICONS = resources/icon.ico # The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the diff --git a/common.cpp b/common.cpp index 7d8cf95..03ca7dc 100644 --- a/common.cpp +++ b/common.cpp @@ -1,4 +1,5 @@ -#include "common.h" +#pragma execution_character_set("utf-8") +#include "common.h" #include #include #include @@ -14,39 +15,47 @@ Common::Common() bool Common::loadConfig(const QString &filePath) { - // 提取网络配置 - QString iniFilePath = filePath + "/network.ini"; - QSettings *configIni = new QSettings(iniFilePath, QSettings::IniFormat); - m_ipAddr = configIni->value("network/ip").toString(); - m_srcPort = configIni->value("network/src_port").toInt(); - m_dstPort = configIni->value("network/dst_port").toInt(); - - m_configFilePath = filePath + "/Config.json"; - std::ifstream jsonStream(m_configFilePath.toLocal8Bit()); - m_configJson = json::parse(jsonStream); - jsonStream.close(); - // 提取工作模式 - auto workmodes = m_configJson.at("workmode"); - for (const auto& workmode : workmodes) + try { - QString name = QString::fromStdString(workmode["name"]); - int index = workmode["index"]; - QString path = QString::fromStdString(workmode["exe_path"]); - QString reworkPath = QString::fromStdString(workmode["rework_exe_path"]); - m_modeConfigs[index] = ModeConfig{index, name, path, reworkPath}; + // 提取网络配置 + QString iniFilePath = filePath + "/network.ini"; + QSettings* configIni = new QSettings(iniFilePath, QSettings::IniFormat); + m_ipAddr = configIni->value("network/ip").toString(); + m_srcPort = configIni->value("network/src_port").toInt(); + m_dstPort = configIni->value("network/dst_port").toInt(); + + m_configFilePath = filePath + "/Config.json"; + std::ifstream jsonStream(m_configFilePath.toLocal8Bit()); + m_configJson = json::parse(jsonStream); + jsonStream.close(); + // 提取工作模式 + auto workmodes = m_configJson.at("workmode"); + for (const auto& workmode : workmodes) + { + QString name = QString::fromStdString(workmode["name"]); + int index = workmode["index"]; + QString path = QString::fromStdString(workmode["exe_path"]); + QString reworkPath = QString::fromStdString(workmode["rework_exe_path"]); + m_modeConfigs[index] = ModeConfig{ index, name, path, reworkPath }; + } + // 提取产品配置 + auto products = m_configJson.at("products"); + for (const auto& product : products) + { + int index = product["index"]; + bool selected = product["selected"]; + int mode = product["mode"]; + QString formatStr = QString::fromStdString(product["format"]); + m_productConfigs[index] = ProductConfig{ index, static_cast(mode), selected, formatStr }; + } + FilterSelectedProducts(); + return true; } - // 提取产品配置 - auto products = m_configJson.at("products"); - for (const auto& product : products) - { - int index = product["index"]; - bool selected = product["selected"]; - int mode = product["mode"]; - QString formatStr = QString::fromStdString(product["format"]); - m_productConfigs[index] = ProductConfig{index, static_cast(mode), selected, formatStr}; + catch(const std::exception& e) + { + LError(QString("Load config file error: %1").arg(e.what())); + return false; } - FilterSelectedProducts(); - return true; } bool Common::saveConfig(const QMap &productsCfg, const QMap &workmodeCfg) @@ -79,6 +88,18 @@ int Common::getDstPort() const return m_dstPort; } +const QString Common::getCurrWorkModeStr() const +{ + if (m_currentMode.load() == -1) + { + return getWorkModeStr(-1); + } + + QString reStr = m_isRepair.load() == 1 ? "反修" : "正常"; + QString logStr = QString("%1-%2").arg(getWorkModeStr(m_currentMode.load())).arg(reStr); + return logStr; +} + bool Common::saveConfig() { std::ofstream outFile(m_configFilePath.toLocal8Bit()); @@ -156,3 +177,23 @@ void Common::setCurrentWorkMode(const int workMode) { m_currentMode.store(workMode); } + +bool Common::getRepairFlag() const +{ + return m_isRepair.load(); +} + +void Common::setRepairFlag(const bool isRepair) +{ + m_isRepair.store(isRepair); +} + +QString Common::getWorkModeStr(int mode) +{ + static QMap modeMap = { {-1, "未连接"}, {2, "GLOBAL_M2M"}, {3, "LOCAL_M2M"}}; + if (!modeMap.contains(mode)) + { + return "unknown mode"; + } + return modeMap[mode]; +} diff --git a/common.h b/common.h index f378aef..f9a278a 100644 --- a/common.h +++ b/common.h @@ -9,6 +9,8 @@ #include "nlohmann/json.hpp" #include "EasySpdLog.h" +#define TEST_MODE + class Common : public QObject, public Singleton { Q_OBJECT @@ -25,6 +27,7 @@ public: // 获取端口号 int getSrcPort() const; int getDstPort() const; + const QString getCurrWorkModeStr() const; // 获取产品配置 QMap getProductConfigs(); // 设置产品配置 @@ -40,6 +43,11 @@ public: // 设置当前工作模式 void setCurrentWorkMode(const int workMode); + bool getRepairFlag() const; + + void setRepairFlag(const bool isRepair); + + static QString getWorkModeStr(int mode); signals: private: @@ -52,12 +60,14 @@ private: nlohmann::json m_configJson{}; QString m_currentWorkPath{}; // 当前工作路径 std::atomic m_currentMode{ -1 }; // 当前正在进行的工作模式 + std::atomic m_isRepair{ false }; QString m_ipAddr{}; int m_dstPort{}; int m_srcPort{}; QMap m_modeConfigs{}; // 模式配置 QMap m_productConfigs{}; // 产品配置 QMap m_selectedProduct{}; // 选择的产品 + std::atomic m_isLockSNLineEdit{false}; }; #endif // COMMON_H diff --git a/main.cpp b/main.cpp index 140b982..2e9baa8 100644 --- a/main.cpp +++ b/main.cpp @@ -1,7 +1,8 @@ -#include "widget.h" +#pragma execution_character_set("utf-8") +#include "widget.h" #include - +#include #include "common.h" #include "EasySpdLog.h" @@ -13,7 +14,11 @@ int main(int argc, char *argv[]) SetLogger(loggerPath.data()); // 加载配置文件 QString filePath = QApplication::applicationDirPath() + "/config"; - Common::GetInstance()->loadConfig(filePath); + if (!Common::GetInstance()->loadConfig(filePath)) + { + QMessageBox::warning(nullptr, "错误", "配置文件加载失败!\n 请检查配置文件是否存在或格式是否正确!"); + return 0; + } // Widget w; w.move(0, 0); diff --git a/network/udpdatahandler.cpp b/network/udpdatahandler.cpp index 77eb2f5..6316304 100644 --- a/network/udpdatahandler.cpp +++ b/network/udpdatahandler.cpp @@ -1,4 +1,5 @@ -#include "udpdatahandler.h" +#pragma execution_character_set("utf-8") +#include "udpdatahandler.h" #include #include "common.h" #include "EasySpdLog.h" @@ -91,6 +92,8 @@ void UdpDataHandler::recvData(const QByteArray &data) { emit GetDoneSig(ret); } + QString snMsg = QString("590200"); + m_udpWorker->sendData(snMsg.toLocal8Bit(), m_hostAddr, Common::GetInstance()->getDstPort()); break; } default: diff --git a/resources.qrc b/resources.qrc index 59b3064..cad6872 100644 --- a/resources.qrc +++ b/resources.qrc @@ -2,5 +2,7 @@ resources/folding.png resources/unfolding.png + resources/icon.ico + resources/icon.png diff --git a/resources/icon.ico b/resources/icon.ico new file mode 100644 index 0000000..a4eb662 Binary files /dev/null and b/resources/icon.ico differ diff --git a/resources/icon.png b/resources/icon.png new file mode 100644 index 0000000..736a12a Binary files /dev/null and b/resources/icon.png differ diff --git a/ui/countdownmessagebox.cpp b/ui/countdownmessagebox.cpp index c3b12f2..769282f 100644 --- a/ui/countdownmessagebox.cpp +++ b/ui/countdownmessagebox.cpp @@ -18,7 +18,7 @@ void CountdownMessageBox::showCountdownMessageBox(QWidget *parent, int timeoutSe { CountdownMessageBox msgBox(timeoutSeconds, parent); msgBox.setWindowTitle(title); - msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + msgBox.setStandardButtons(QMessageBox::Ok); msgBox.exec(); } diff --git a/ui/settingwgt.cpp b/ui/settingwgt.cpp index a7d0bc7..c536574 100644 --- a/ui/settingwgt.cpp +++ b/ui/settingwgt.cpp @@ -163,6 +163,7 @@ void SettingWgt::onCheckBoxStateChanged(int index) void SettingWgt::SelectPathButton_clicked(int index, bool isRework) { + LTrace("Function enter"); // 定义选择的路径和是否是 reworkPath 的标志 QString exe_path = QFileDialog::getOpenFileName(this, tr("选择可执行程序"), QCoreApplication::applicationDirPath(), @@ -183,6 +184,7 @@ void SettingWgt::SelectPathButton_clicked(int index, bool isRework) void SettingWgt::on_pushButton_ok_clicked() { + LTrace("Function enter"); for (int i = 0 ; i < m_productNums; ++i) { m_productsCfg[i + 1].selected = m_selectCheckBoxes[i]->isChecked(); diff --git a/ui/widget.cpp b/ui/widget.cpp index 1ece6aa..4b28f0c 100644 --- a/ui/widget.cpp +++ b/ui/widget.cpp @@ -2,14 +2,20 @@ #include "widget.h" #include "ui_widget.h" +#include +#include + +#include #include #include #include -#include + #include #include #include #include +#include + #include "countdownmessagebox.h" #include "common.h" @@ -23,7 +29,6 @@ Widget::Widget(QWidget *parent) , m_settingDlg(new SettingWgt(this)) , m_udpDataThread(new UdpDataHandler(this)) , m_showSetting(false) - , m_isSwitching(false) { ui->setupUi(this); @@ -31,18 +36,27 @@ Widget::Widget(QWidget *parent) connect(m_settingDlg, &SettingWgt::SettingFinishSig, this, &Widget::on_pushButton_setting_clicked); connect(m_udpDataThread, &UdpDataHandler::GetDoneSig, this, &Widget::RegisterDoneSlot); connect(m_udpDataThread, &UdpDataHandler::GetConnStatusSig, this, &Widget::GetConnStatusSlot); + addLogItem("程序初始化成功!"); + + ProcessJudgment(); } Widget::~Widget() { delete ui; + if (m_db.isOpen()) + { + m_db.close(); + QSqlDatabase::removeDatabase(QSqlDatabase::defaultConnection); + } } void Widget::initUI() { - this->setWindowTitle(""); - //this->setWindowFlags(Qt::Window | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint | Qt::CustomizeWindowHint); - this->setWindowFlags(Qt::Window | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint | Qt::CustomizeWindowHint); + this->setWindowTitle("LaunchRegisterKey"); + this->setWindowFlags(Qt::Window | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint | Qt::CustomizeWindowHint); + //this->setWindowFlags(Qt::Window | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint | Qt::CustomizeWindowHint); + this->setWindowIcon(QIcon(":/resources/icon.ico")); ui->list_log->setEditTriggers(QAbstractItemView::NoEditTriggers); QHBoxLayout *layout = new QHBoxLayout(this); layout->addWidget(m_settingDlg); @@ -54,7 +68,11 @@ void Widget::initUI() void Widget::setSNLineEditFocus() { // 全选LineEdit并且焦点放在LineEdit上 - ui->lineEdit_snId->selectAll(); +#ifdef TEST_MODE + QString tmpSn = ui->lineEdit_snId->text(); + ui->lineEdit_snId->setText("1234567890123456"); +#endif + ui->lineEdit_snId->clear(); ui->lineEdit_snId->setFocus(); } @@ -63,6 +81,7 @@ int Widget::checkSNId(const QString &snId) if (snId.isEmpty()) { QMessageBox::warning(this, "产品SN错误", "产品SN为空! 请重新扫码!"); + addLogItem("产品SN为空! 请重新扫码!"); LWarn("Product SN id is empty!"); return SNEmptyError; } @@ -70,6 +89,7 @@ int Widget::checkSNId(const QString &snId) if (reg.indexIn(snId) != -1) { QMessageBox::information(this,"提示",QString("产品SN(%1)包含小写! 请重新扫码!").arg(snId)); + addLogItem(QString("产品SN(%1)包含小写! 请重新扫码!").arg(snId)); LWarn("Product SN contains lowercase!"); ui->lineEdit_snId->setText(""); return SNLowerCaseError; @@ -77,6 +97,7 @@ int Widget::checkSNId(const QString &snId) if (snId.contains(" ")) { QMessageBox::information(this,"提示",QString("产品SN(%1)包含空格! 请重新扫码!").arg(snId)); + addLogItem(QString("产品SN(%1)包含空格! 请重新扫码!").arg(snId)); LWarn("Product SN contains Spaces!"); ui->lineEdit_snId->setText(""); return SNSpaceError; @@ -86,15 +107,22 @@ int Widget::checkSNId(const QString &snId) int Widget::startIECSProgram(const QString& workPath, const QString& snId) { + LInfo("Function enter"); QProcess *process = new QProcess(this); - process->start(workPath); + connect(process, QOverload::of(&QProcess::finished), + process, &QProcess::deleteLater); + // 使用 cmd.exe 来启动进程并使用 start 命令使其脱离父进程 + QString command = QString("cmd.exe /C start \"\" \"%1\"").arg(workPath); + process->start(command); + if (!process->waitForStarted()) { - LError("Failed to start the program with arguments:{}", process->errorString()); + LError("Failed to start the program with arguments: {}", process->errorString()); + process->deleteLater(); + addLogItem(QString("%1启动失败!").arg(workPath)); return ExecIECSError; } - m_udpDataThread->sendSnId(snId); - m_isSwitching = false; + LInfo("Process started: {}", workPath); return NoError; } @@ -113,19 +141,31 @@ int Widget::checkForRepairProgram(const int mode, const QString& sn, bool& isFin int Widget::databaseQuery(const QString& databasePath, const QString& deviceSn, bool& isFind) { - // 创建和打开 SQLite 数据库 - QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); - db.setDatabaseName(databasePath); // 使用传入的数据库路径 + // 静态变量来保存上一次使用的数据库路径 + static QString previousDatabasePath; + // 如果数据库路径发生变动,关闭之前的连接并移除数据库 + if (m_db.isOpen() && previousDatabasePath != databasePath) { + m_db.close(); + QSqlDatabase::removeDatabase(QSqlDatabase::defaultConnection); + } - if (!db.open()) - { - LError("Failed to open database:{}", db.lastError().text()); - isFind = false; - return DatabaseOpenError; + // 如果数据库尚未打开或路径已变动,重新打开数据库 + if (!m_db.isOpen() || previousDatabasePath != databasePath) { + m_db = QSqlDatabase::addDatabase("QSQLITE"); + m_db.setDatabaseName(databasePath); // 使用传入的数据库路径 + + if (!m_db.open()) { + LError("Failed to open database:{}", m_db.lastError().text()); + isFind = false; + return DatabaseOpenError; + } + + // 更新路径 + previousDatabasePath = databasePath; } // 创建查询对象 - QSqlQuery query(db); + QSqlQuery query(m_db); // 准备 SQL 查询 query.prepare("SELECT COUNT(1) FROM history WHERE device_sn = :device_sn;"); @@ -135,44 +175,209 @@ int Widget::databaseQuery(const QString& databasePath, const QString& deviceSn, if (!query.exec()) { LError("Failed to execute query:{}", query.lastError().text()); isFind = false; - db.close(); - QSqlDatabase::removeDatabase(QSqlDatabase::defaultConnection); return DatabaseSelectError; } // 处理查询结果 - if (query.next()) - { + if (query.next()) { int count = query.value(0).toInt(); isFind = (count > 0); - db.close(); - QSqlDatabase::removeDatabase(QSqlDatabase::defaultConnection); return NoError; } isFind = false; - db.close(); - QSqlDatabase::removeDatabase(QSqlDatabase::defaultConnection); return DatabaseUnknownError; } +// 判断是否为单板 SN +static bool isSingleBoardSN(const QString& sn) { + // 单板 SN 格式:9位前缀-固定12位尾数 + QRegularExpression regex("^\\d{9}-[A-Z0-9]{12}$"); + return regex.match(sn).hasMatch(); +} + +// 判断是否为整机 SN +static bool isCompleteMachineSN(const QString& sn) { + // 整机 SN 格式:前25位前缀-固定8位尾数 + QRegularExpression regex("^.{25}[A-Z0-9]{10,}$"); + return sn.contains('#') && regex.match(sn).hasMatch(); +} + +bool Widget::identifyProduct(const QString &sn, int &mode) +{ + const auto selectedProducts = Common::GetInstance()->getSelectedProducts(); + if (isSingleBoardSN(sn)) + { + QString productKey = sn.mid(9); // 提取单板 SN 的尾数部分 + if (selectedProducts.contains(productKey)) + { + mode = selectedProducts[productKey]; + return true; // 返回匹配的产品名称 + } + } + else if (isCompleteMachineSN(sn)) + { + QString productKey = sn.mid(25); // 提取整机 SN 的尾数部分 + if (selectedProducts.contains(productKey)) + { + mode = selectedProducts[productKey]; + return true; // 返回匹配的产品名称 + } + } + return false; +} + void Widget::RegisterDoneSlot(bool ret) { - qDebug()<<"11111"; + if (ret) + { + addLogItem("注KEY成功"); + } + else + { + addLogItem("注KEY失败,请检查对应程序注KEY详情!"); + } ui->lineEdit_snId->setEnabled(true); + ui->pushButton_sendSnId->setEnabled(true); + setSNLineEditFocus(); } void Widget::GetConnStatusSlot(bool ret) { - if (!ret && !m_isSwitching) + if (ret) { - qDebug()<<"ret:"<lineEdit_snId->setEnabled(true); + //Common::GetInstance()-> + setWindowTitle(QString("LaunchRegisterKey-已连接")); + } + else + { + setWindowTitle("LaunchRegisterKey-未连接"); + } } +// 辅助函数:比较进程路径和目标路径 +static bool isMatchingProcess(const QString& processPath, const QString& targetPath) { + return processPath.compare(targetPath, Qt::CaseInsensitive) == 0; +} + +bool Widget::ProcessJudgment() +{ + // 创建一个快照来获取当前系统的所有进程 + HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hProcessSnap == INVALID_HANDLE_VALUE) + { + qWarning() << "Failed to create process snapshot."; + return false; + } + + PROCESSENTRY32 pe32{}; + pe32.dwSize = sizeof(PROCESSENTRY32); + + if (!Process32First(hProcessSnap, &pe32)) + { + qWarning() << "Failed to retrieve process information."; + CloseHandle(hProcessSnap); + return false; + } + + const auto& workModeCfgs = Common::GetInstance()->getWorkModeConfigs(); + + do { + HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pe32.th32ProcessID); + if (!hProcess) + { + continue; // 无法打开进程,继续下一个进程 + } + + WCHAR exePath[MAX_PATH]; + DWORD size = MAX_PATH; + if (QueryFullProcessImageName(hProcess, 0, exePath, &size)) + { + QString processPath = QDir::fromNativeSeparators(QString::fromWCharArray(exePath)); + + for (const auto& workmodeCfg : workModeCfgs) + { + int matchedType = -1; // 用于保存匹配的路径类型 + + if (isMatchingProcess(processPath, workmodeCfg.workPath)) + { + matchedType = 0; // workPath 匹配 + } + else if (isMatchingProcess(processPath, workmodeCfg.reworkPath)) + { + matchedType = 1; // reworkPath 匹配 + } + + if (matchedType != -1) + { + Common::GetInstance()->setCurrentWorkMode(workmodeCfg.index); + Common::GetInstance()->setRepairFlag(matchedType == 1); // 如果是 reworkPath,设置为 true + + QString logStr = QString("正在使用%1").arg(Common::GetInstance()->getCurrWorkModeStr()); + addLogItem(logStr); + qDebug() << "Matching process found:" + << QString::fromWCharArray(pe32.szExeFile) + << "PID:" << pe32.th32ProcessID + << "Path:" << processPath + << "Matched Type:" << (matchedType == 0 ? "workPath" : "reworkPath"); + + CloseHandle(hProcess); + CloseHandle(hProcessSnap); + return true; + } + } + } + CloseHandle(hProcess); // 确保句柄被关闭 + } while (Process32Next(hProcessSnap, &pe32)); + + CloseHandle(hProcessSnap); + qDebug() << "No matching process found."; + return false; +} + +bool Widget::isProcessRunningWithName(const QString& processNamePart) +{ + // 创建一个快照来获取当前系统的所有进程 + HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hProcessSnap == INVALID_HANDLE_VALUE) { + qWarning() << "Failed to create process snapshot."; + return false; + } + + // 初始化进程信息结构体 + PROCESSENTRY32 pe32; + pe32.dwSize = sizeof(PROCESSENTRY32); + + // 获取第一个进程信息 + if (!Process32First(hProcessSnap, &pe32)) { + qWarning() << "Failed to retrieve process information."; + CloseHandle(hProcessSnap); + return false; + } + + // 遍历所有进程 + do { + // 将进程名称转换为QString + QString processName = QString::fromWCharArray(pe32.szExeFile); + + // 判断进程名称是否包含指定字符串 + if (processName.contains(processNamePart, Qt::CaseInsensitive)) { + qDebug() << "Found matching process:" << processName; + CloseHandle(hProcessSnap); + return true; // 找到匹配的进程,返回 true + } + + } while (Process32Next(hProcessSnap, &pe32)); + + // 关闭快照句柄 + CloseHandle(hProcessSnap); + return false; +} + void Widget::on_pushButton_setting_clicked() { + static auto initSize = this->size(); if (ui->widget_setting->isHidden()) { ui->pushButton_setting->setIcon(QIcon(":/resources/folding.png")); @@ -188,7 +393,7 @@ void Widget::on_pushButton_setting_clicked() ui->widget_setting->hide(); int currentWidth = this->width(); this->adjustSize(); - this->resize(currentWidth, this->height()); // 只保持高度变化 + this->resize(initSize); // 只保持高度变化 setSNLineEditFocus(); } } @@ -199,16 +404,19 @@ void Widget::addLogItem(const QString &text) { delete ui->list_log->takeItem(0); } - ui->list_log->addItem(text); // 添加新条目 + QString dateTimeStr = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"); + ui->list_log->addItem(dateTimeStr + " " + text); // 添加新条目 + ui->list_log->scrollToBottom(); // 滚动到底部 } int Widget::switchProgram(const QString snId, const int mode, const bool isRepair) { + LTrace("Function enter"); static bool isFirstRepair = true; if (isRepair && isFirstRepair) { isFirstRepair = false; - CountdownMessageBox::showCountdownMessageBox(this, 3, "正在切换返修程序包!"); + CountdownMessageBox::showCountdownMessageBox(this, 3, "启用返修程序包!"); } else if (!isRepair) { @@ -220,13 +428,38 @@ int Widget::switchProgram(const QString snId, const int mode, const bool isRepai QTimer *timer = new QTimer(this); connect(timer, &QTimer::timeout, this, [this, timer, snId, workPath]() { + static int times = 0; if (Common::GetInstance()->getCurrentWorkMode() == -1) { - m_isSwitching = true; m_udpDataThread->stopClose(); - timer->stop(); // 停止定时器 - // 启动 IECS 程序 - startIECSProgram(workPath, snId); + if (!isProcessRunningWithName("IECS")) + { + timer->stop(); // 停止定时器 + times = 0; + // 启动 IECS 程序 + if (startIECSProgram(workPath, snId) != NoError) + { + ui->lineEdit_snId->setEnabled(true); + ui->pushButton_sendSnId->setEnabled(true); + QMessageBox::warning(this, "程序启动失败!", QString("启动%1失败,请检查程序路径").arg(workPath)); + return; + } + // 发送 SN ID 和记录日志 + m_udpDataThread->sendSnId(snId); + addLogItem(QString("已发送产品SN:%1").arg(snId)); + } + else + { + times++; + if (times >= 10) + { + times = 0; + timer->stop(); + ui->lineEdit_snId->setEnabled(true); + ui->pushButton_sendSnId->setEnabled(true); + QMessageBox::warning(this, "程序启动失败!", QString("启动%1失败,进程已存在").arg(workPath)); + } + } } }); timer->start(1000); @@ -235,6 +468,7 @@ int Widget::switchProgram(const QString snId, const int mode, const bool isRepai void Widget::on_lineEdit_snId_returnPressed() { + LTrace("Function enter"); QString snId = ui->lineEdit_snId->text(); int ret = 0; ret = checkSNId(snId); @@ -243,45 +477,44 @@ void Widget::on_lineEdit_snId_returnPressed() LError("checkSNId error!code:{}", ret); return; } - const auto selectedProducts = Common::GetInstance()->getSelectedProducts(); - QString productFormat{}; - for (auto& products : selectedProducts.keys()) - { - if (snId.contains(products)) - { - productFormat = products; - break; - } - } - if (productFormat.isEmpty()) + int snMode = -1; + if (!identifyProduct(snId, snMode)) { QMessageBox::information(this, "警告", "当前SN与启用设值SN不匹配,请检查设置或重新扫码"); return; } ui->lineEdit_snId->setEnabled(false); + ui->pushButton_sendSnId->setEnabled(false); + LInfo("SN ID:{}, Mode:{}", snId, snMode); auto currWorkMode = Common::GetInstance()->getCurrentWorkMode(); + bool repairFlag = Common::GetInstance()->getRepairFlag(); bool isRepair = false; // 查找数据库,判断是否需要返修程序 - ret = checkForRepairProgram(selectedProducts[productFormat], snId, isRepair); + ret = checkForRepairProgram(snMode, snId, isRepair); if (ret != NoError) { LError("checkForRepairProgram error!{}", ret); return; } - auto selectMode = selectedProducts[productFormat]; - if (selectMode != currWorkMode || isRepair) + if (snMode != currWorkMode || isRepair != repairFlag) { + Common::GetInstance()->setRepairFlag(isRepair); + QString reStr = isRepair ? "反修" : "正常"; + QString logStr = QString("启动%1-%2").arg(Common::getWorkModeStr(snMode)).arg(reStr); + addLogItem(logStr); // 切换工作模式 if (currWorkMode != -1) { m_udpDataThread->sendClose(); } + //TODO:不相等时,m_udpDataThread发送关闭信号,等待Common单例类中的标志位变成-1后,m_udpDataThread停止发送关闭信号并启动IECS程序 //同时需要去IECS程序路径中查找数据库,判断是否使用返修程序 - switchProgram(snId, selectMode, isRepair); + switchProgram(snId, snMode, isRepair); return; } m_udpDataThread->sendSnId(snId); + addLogItem(QString("已发送产品SN:%1").arg(snId)); } void Widget::on_pushButton_sendSnId_clicked() diff --git a/ui/widget.h b/ui/widget.h index 7dc2815..a3ca2a1 100644 --- a/ui/widget.h +++ b/ui/widget.h @@ -2,6 +2,8 @@ #define WIDGET_H #include +#include + #include "settingwgt.h" #include "udpdatahandler.h" @@ -23,20 +25,27 @@ private: int checkForRepairProgram(const int mode, const QString& sn, bool& isFind); int databaseQuery(const QString& databasePath, const QString& deviceSn, bool& isFind); + + bool identifyProduct(const QString& sn, int& mode); + private slots: void RegisterDoneSlot(bool ret); void GetConnStatusSlot(bool ret); + bool ProcessJudgment(); + bool isProcessRunningWithName(const QString& processNamePart); + void addLogItem(const QString& text); int switchProgram(const QString snId, const int mode, const bool isRepair); void on_pushButton_setting_clicked(); void on_lineEdit_snId_returnPressed(); void on_pushButton_sendSnId_clicked(); + private: Ui::Widget *ui; SettingWgt *m_settingDlg; UdpDataHandler *m_udpDataThread; bool m_showSetting; - bool m_isSwitching; + QSqlDatabase m_db; }; #endif // WIDGET_H diff --git a/utils/interface.h b/utils/interface.h index 3448302..ab6eab2 100644 --- a/utils/interface.h +++ b/utils/interface.h @@ -1,6 +1,7 @@ #ifndef INTERFACE_H #define INTERFACE_H #include +#include enum ErrorCode { NoError = 0,