V1.7
authorxue <2144439972@qq.com>
Mon, 13 Apr 2026 07:04:00 +0000 (15:04 +0800)
committerxue <2144439972@qq.com>
Mon, 13 Apr 2026 07:04:00 +0000 (15:04 +0800)
1.增加关机按钮
2.修复LCD会进入用户模式的bug
3.保存文件增加mac地址

mainwindow.cpp
mainwindow.h
mainwindow.ui

index a6c35d3..95171cc 100644 (file)
 #include <QBrush>
 #include <QGraphicsView>
 #include <QResizeEvent>
+#include <QFileInfo>
+
+namespace {
+QString macTagForFilename(const QString &mac)
+{
+    if (mac.trimmed().isEmpty()) {
+        return QStringLiteral("UNKNOWN");
+    }
+    QString t = mac.trimmed().toUpper();
+    t.remove(QLatin1Char(':'));
+    for (int i = 0; i < t.size(); ++i) {
+        const QChar c = t.at(i);
+        if (!c.isDigit() && (c < QLatin1Char('A') || c > QLatin1Char('F'))) {
+            t[i] = QLatin1Char('_');
+        }
+    }
+    return t.isEmpty() ? QStringLiteral("UNKNOWN") : t;
+}
+
+QString macForCsvColumn(const QString &mac)
+{
+    return mac.trimmed().isEmpty() ? QStringLiteral("未获取") : mac.trimmed();
+}
+} // namespace
 
 MainWindow::MainWindow(QWidget *parent)
     : QMainWindow(parent)
@@ -106,6 +130,7 @@ MainWindow::MainWindow(QWidget *parent)
     testLogFile = nullptr;
     testLogStream = nullptr;
     testLogFilePath = "";
+    productionDeviceMac.clear();
     // 初始化配置管理器
     configManager.loadConfig();
     // 初始化开机检测相关变量
@@ -545,11 +570,9 @@ void MainWindow::readSerialData()
             CheckVibratorFunc(processLine);
         }
 
-        // 检测wstp_print格式的BTMAC和CyweeChipInfo数据(不需要fac:开头)
-        if (line.contains("^^^^ BTMAC=") && line.contains("^^^^ CyweeChipInfo=")) {
-            // 显示到接收区
+        // 检测wstp_print格式的BTMAC和/或CyweeChipInfo数据(不需要fac:开头)
+        if (line.contains("^^^^ BTMAC=") || line.contains("^^^^ CyweeChipInfo=")) {
             appendToLogFile(line);
-            
             parseWstpPrintData(line);
         }
         
@@ -749,171 +772,39 @@ void MainWindow::on_ProductionTestButton_clicked()
     }
 }
 
-// LCD测试函数
+// LCD测试:仅发送 AT^LCDTEST=1,不再发送变色/退出/关屏等其它 LCD 相关 AT
 void MainWindow::performLcdTest()
 {
-    // 检查LCD测试是否启用
     if (!isTestItemEnabled("lcd")) {
         qDebug() << "LCD测试未启用,跳过";
         updateTestStatus("lcd", STATUS_UNTESTED);
         skipToNextEnabledTest();
         return;
     }
-    
+
     if (!isProductionTestRunning || currentTestStep != TEST_LCD) {
         qDebug() << "LCD测试跳过 - 产测运行:" << isProductionTestRunning << "当前步骤:" << currentTestStep;
         return;
     }
 
-    // 第一次进入LCD测试时更新状态并发送进入LCD测试模式指令
-    if (currentLcdColor == 1) {
-        ui->recvTextEdit->append("========== 开始LCD测试 ==========");
-        updateTestStatus("lcd", STATUS_TESTING);
-        
-        // 发送进入LCD测试模式指令
-        serial->write("AT^LCDTEST=1\r\n");
-        qDebug() << "发送进入LCD测试模式指令: AT^LCDTEST=1";
-        ui->statusbar->showMessage("进入LCD测试模式,1秒后开始颜色测试...", 1000);
-        
-        // 延迟1秒后开始颜色测试,确保设备完全进入LCD测试模式
-        QTimer::singleShot(1000, this, [this]() {
-            if (isProductionTestRunning && currentTestStep == TEST_LCD) {
-                qDebug() << "LCD测试模式初始化完成,开始颜色测试";
-                performLcdColorTest();
-            }
-        });
-        return;
-    }
-    
-    // 直接执行颜色测试
-    performLcdColorTest();
-}
+    ui->recvTextEdit->append("========== 开始LCD测试 ==========");
+    updateTestStatus("lcd", STATUS_TESTING);
 
-// LCD颜色测试函数
-void MainWindow::performLcdColorTest()
-{
-    if (!isProductionTestRunning || currentTestStep != TEST_LCD) {
-        qDebug() << "LCD颜色测试跳过 - 产测运行:" << isProductionTestRunning << "当前步骤:" << currentTestStep;
-        return;
-    }
-    
-    qDebug() << "LCD测试 - 测试步骤:" << currentLcdColor << "定时器状态:" << lcdTestTimer->isActive();
-    
-    // 在第一个颜色(红色)开始时就显示确认弹窗
-    if (currentLcdColor == 1 && !lcdTestPopupShown) {
-        qDebug() << "LCD测试开始,显示确认弹窗";
-        // 延迟一点显示弹窗,让红色先显示
-        QTimer::singleShot(500, this, [this]() {
-            if (isProductionTestRunning && currentTestStep == TEST_LCD && !lcdTestPopupShown) {
-                showLcdTestConfirmDialog();
-            }
-        });
-    }
-    
-    QString colorName;
-    int colorCommand;
-    switch (currentLcdColor) {
-    case 1:
-            colorName = "红色"; 
-            colorCommand = 6; // AT^LCDTEST=6 红色
-        break;
-    case 2:
-            colorName = "绿色"; 
-            colorCommand = 3; // AT^LCDTEST=3 绿色
-        break;
-    case 3:
-            colorName = "蓝色"; 
-            colorCommand = 4; // AT^LCDTEST=4 蓝色
-        break;
-    default:
-            colorName = "未知";
-            colorCommand = 6;
-        break;
-    }
-    
-    ui->statusbar->showMessage("LCD测试中 - " + colorName + " (1秒)", 1000);
-    
-    // 发送LCD测试指令,使用正确的颜色映射
-    QString command = QString("AT^LCDTEST=%1\r\n").arg(colorCommand);
-    serial->write(command.toUtf8());
-    qDebug() << "发送LCD指令:" << command.trimmed() << "(" << colorName << ")";
-    
-    // 设置1秒定时器
-    lcdTestTimer->start(1000);
+    serial->write("AT^LCDTEST=1\r\n");
+    qDebug() << "LCD测试仅发送: AT^LCDTEST=1";
+    ui->statusbar->showMessage("已发送 AT^LCDTEST=1,请观察屏幕", 3000);
+
+    QTimer::singleShot(800, this, [this]() {
+        if (isProductionTestRunning && currentTestStep == TEST_LCD && !lcdTestPopupShown) {
+            showLcdTestConfirmDialog();
+        }
+    });
 }
 
-// LCD测试定时器槽函数
+// LCD 颜色轮询已移除;定时器保留连接,避免误触发时无操作
 void MainWindow::onLcdTestTimer()
 {
     lcdTestTimer->stop();
-    qDebug() << "LCD定时器触发,当前颜色:" << currentLcdColor;
-    
-    if (!isProductionTestRunning) {
-        qDebug() << "产测未运行,退出定时器";
-        return;
-    }
-    
-    currentLcdColor++;
-    qDebug() << "切换到下一个颜色:" << currentLcdColor;
-    
-    if (currentLcdColor <= 3) {
-        // 继续下一个颜色测试
-        qDebug() << "继续下一个颜色测试";
-        performLcdColorTest();
-    } else {
-        // LCD测试完成,发送退出LCD测试指令
-        qDebug() << "LCD测试完成,退出LCD测试界面";
-        ui->statusbar->showMessage("LCD测试完成,退出测试界面", 1000);
-        
-        // 发送退出LCD测试指令
-        serial->write("AT^LCDTEST=2\r\n");
-        qDebug() << "发送LCD退出指令: AT^LCDTEST=2";
-        
-        // 如果LCD测试被选中且LCD是开启状态,才需要关闭LCD
-        if (isTestItemEnabled("lcd") && lcdBacklightOn) {
-            // 发送关闭LCD指令
-            QTimer::singleShot(100, this, [this]() {
-                if (isProductionTestRunning && serial && serial->isOpen()) {
-                    serial->write("AT^LCDOFF\r\n");
-                    qDebug() << "发送指令: AT^LCDOFF (关闭LCD)";
-                    ui->recvTextEdit->append(">>> 发送指令: AT^LCDOFF (关闭LCD)");
-                    
-                    // LCD关闭后延迟1秒,然后延迟2秒再继续下一个测试
-                    QTimer::singleShot(1000, this, [this]() {
-                        // LCD颜色测试完成,检查用户是否已确认
-                        if (!isWaitingForUserConfirm) {
-                            // 用户已确认,延迟2秒后继续下一个测试
-                            QTimer::singleShot(2000, this, [this]() {
-                                if (isProductionTestRunning) {
-                                    qDebug() << "用户已确认LCD结果,推进到下一个测试";
-                                    skipToNextEnabledTest();
-                                }
-                            });
-                        } else {
-                            // 用户还未确认,等待用户确认后再继续
-                            qDebug() << "LCD颜色测试完成,等待用户确认结果";
-                            ui->statusbar->showMessage("LCD测试完成,等待用户确认结果", 3000);
-                        }
-                    });
-                }
-            });
-        } else {
-            // LCD测试未启用或LCD已关闭,直接继续
-            if (!isWaitingForUserConfirm) {
-                // 用户已确认,延迟2秒后继续下一个测试
-                QTimer::singleShot(2000, this, [this]() {
-                    if (isProductionTestRunning) {
-                        qDebug() << "用户已确认LCD结果,推进到下一个测试";
-                        skipToNextEnabledTest();
-                    }
-                });
-            } else {
-                // 用户还未确认,等待用户确认后再继续
-                qDebug() << "LCD颜色测试完成,等待用户确认结果";
-                ui->statusbar->showMessage("LCD测试完成,等待用户确认结果", 3000);
-            }
-        }
-    }
 }
 
 // 马达测试函数
@@ -1104,29 +995,10 @@ void MainWindow::checkFactoryModeResult(const QString& data)
     }
 }
 
-// 检查LCD测试结果
+// 检查LCD测试结果(已改为仅发 AT^LCDTEST=1 + 延时弹窗确认,不再依赖串口触发)
 void MainWindow::checkLcdTestResult(const QString& data)
 {
-    // 检测LCD测试回复信息,并且只在LCD测试阶段且未显示过弹窗时弹出
-    // 修改:在最后一个颜色(蓝色)显示时才弹窗,让用户观察完整过程
-    if (data.contains("LCD test") && currentTestStep == TEST_LCD && 
-        !lcdTestPopupShown && isProductionTestRunning && currentLcdColor >= 3) {
-        
-        qDebug() << "检测到LCD测试回复:" << data.trimmed();
-        qDebug() << "准备显示LCD测试确认弹窗";
-        
-        // 标记弹窗已显示,避免重复弹出
-        lcdTestPopupShown = true;
-        isWaitingForUserConfirm = true;
-        
-        // 注意:不暂停LCD定时器,让颜色切换继续进行
-        // LCD颜色切换应该独立于用户确认过程
-        qDebug() << "显示LCD确认弹窗,但颜色切换继续进行";
-        
-        // LCD测试回复已检测到,弹窗处理由performLcdTest中的定时器处理
-        
-        // 不需要在这里处理弹窗,由performLcdTest中的定时器处理
-    }
+    Q_UNUSED(data);
 }
 
 // 显示LCD测试确认弹窗
@@ -1146,8 +1018,8 @@ void MainWindow::showLcdTestConfirmDialog()
         // 弹出确认对话框让测试人员确认LCD显示是否正常
         QMessageBox msgBox(this);
         msgBox.setWindowTitle("LCD测试确认");
-    msgBox.setText("LCD测试正在进行,请观察LCD是否正常显示红、绿、蓝、白色切换");
-    msgBox.setInformativeText("观察完成后请选择LCD显示结果:");
+    msgBox.setText("已发送 AT^LCDTEST=1,请观察 LCD 显示是否正常");
+    msgBox.setInformativeText("观察完成后请选择结果:");
         msgBox.setIcon(QMessageBox::Question);
     
     // 设置弹窗尺寸更大
@@ -1209,138 +1081,30 @@ void MainWindow::showLcdTestConfirmDialog()
         
         // 根据用户选择处理结果
         if (msgBox.clickedButton() == successButton) {
-            // 测试人员确认LCD显示正常
             qDebug() << "测试人员确认:LCD显示正常";
             ui->statusbar->showMessage("LCD显示正常", 2000);
-        updateTestStatus("lcd", STATUS_SUCCESS);
-        
-        // 发送停止LCD测试指令
-        serial->write("AT^LCDTEST=2\r\n");
-        qDebug() << "LCD测试通过,发送停止LCD测试指令: AT^LCDTEST=2";
-        
-        // 如果LCD测试被选中且LCD是开启状态,才需要关闭LCD
-        if (isTestItemEnabled("lcd") && lcdBacklightOn) {
-            // 发送关闭LCD指令
-            QTimer::singleShot(100, this, [this]() {
-                if (isProductionTestRunning && serial && serial->isOpen()) {
-                    serial->write("AT^LCDOFF\r\n");
-                    qDebug() << "发送指令: AT^LCDOFF (关闭LCD)";
-                    ui->recvTextEdit->append(">>> 发送指令: AT^LCDOFF (关闭LCD)");
-                    
-                    // LCD关闭后延迟1秒,然后延迟2秒再继续下一个测试
-                    QTimer::singleShot(1000, this, [this]() {
-                        // 停止LCD定时器,防止继续切换颜色和重复调用马达测试
-                        if (lcdTestTimer->isActive()) {
-                            lcdTestTimer->stop();
-                            qDebug() << "停止LCD定时器,防止继续切换颜色和重复调用马达测试";
-                        }
-                        
-                        // 推进到下一个启用的测试
-                        if (isProductionTestRunning) {
-                            qDebug() << "LCD测试通过确认,延迟2秒后推进到下一个测试";
-                            qDebug() << "当前产测状态:" << isProductionTestRunning << "当前测试步骤:" << currentTestStep;
-                            
-                            // 延迟2秒确保LCD完全关闭,然后推进到下一个测试
-                            QTimer::singleShot(2000, this, [this]() {
-                                if (isProductionTestRunning) {
-                                    skipToNextEnabledTest();
-                                }
-                            });
-                        } else {
-                            qDebug() << "产测未运行,无法继续测试";
-                        }
-                    });
-                }
-            });
-        } else {
-            // LCD测试未启用或LCD已关闭,直接继续
-            // 停止LCD定时器,防止继续切换颜色和重复调用马达测试
+            updateTestStatus("lcd", STATUS_SUCCESS);
             if (lcdTestTimer->isActive()) {
                 lcdTestTimer->stop();
-                qDebug() << "停止LCD定时器,防止继续切换颜色和重复调用马达测试";
-            }
-            
-            // 推进到下一个启用的测试
-            if (isProductionTestRunning) {
-                qDebug() << "LCD测试通过确认,延迟2秒后推进到下一个测试";
-                qDebug() << "当前产测状态:" << isProductionTestRunning << "当前测试步骤:" << currentTestStep;
-                
-                // 延迟2秒确保LCD完全关闭,然后推进到下一个测试
-                QTimer::singleShot(2000, this, [this]() {
-                    if (isProductionTestRunning) {
-                        skipToNextEnabledTest();
-                    }
-                });
-            } else {
-                qDebug() << "产测未运行,无法继续测试";
             }
-        }
-            
+            QTimer::singleShot(2000, this, [this]() {
+                if (isProductionTestRunning) {
+                    skipToNextEnabledTest();
+                }
+            });
         } else if (msgBox.clickedButton() == failButton) {
-            // 测试人员确认LCD显示异常
             qDebug() << "测试人员确认:LCD显示异常";
             ui->statusbar->showMessage("LCD显示异常!", 2000);
-        updateTestStatus("lcd", STATUS_FAILED);
-        
-        // 发送停止LCD测试指令
-        serial->write("AT^LCDTEST=2\r\n");
-        qDebug() << "LCD测试失败,发送停止LCD测试指令: AT^LCDTEST=2";
-        
-        // 如果LCD测试被选中且LCD是开启状态,才需要关闭LCD
-        if (isTestItemEnabled("lcd") && lcdBacklightOn) {
-            // 发送关闭LCD指令
-            QTimer::singleShot(100, this, [this]() {
-                if (isProductionTestRunning && serial && serial->isOpen()) {
-                    serial->write("AT^LCDOFF\r\n");
-                    qDebug() << "发送指令: AT^LCDOFF (关闭LCD)";
-                    ui->recvTextEdit->append(">>> 发送指令: AT^LCDOFF (关闭LCD)");
-                    
-                    // LCD关闭后延迟1秒,然后延迟2秒再继续下一个测试
-                    QTimer::singleShot(1000, this, [this]() {
-                        // 停止LCD定时器,防止重复调用马达测试
-                        if (lcdTestTimer->isActive()) {
-                            lcdTestTimer->stop();
-                            qDebug() << "停止LCD定时器,防止重复调用马达测试";
-                        }
-                        
-                        // 即使失败也继续下一个测试
-                        if (isProductionTestRunning) {
-                            qDebug() << "LCD测试失败确认,延迟2秒后继续下一个测试";
-                            qDebug() << "当前产测状态:" << isProductionTestRunning << "当前测试步骤:" << currentTestStep;
-                            
-                            // 延迟2秒确保LCD完全关闭,然后继续下一个测试
-                            QTimer::singleShot(2000, this, [this]() {
-                                if (isProductionTestRunning) {
-                                    skipToNextEnabledTest();
-                                }
-                            });
-                        }
-                    });
-                }
-            });
-        } else {
-            // LCD测试未启用或LCD已关闭,直接继续
-            // 停止LCD定时器,防止重复调用马达测试
+            updateTestStatus("lcd", STATUS_FAILED);
             if (lcdTestTimer->isActive()) {
                 lcdTestTimer->stop();
-                qDebug() << "停止LCD定时器,防止重复调用马达测试";
             }
-            
-            // 即使失败也继续下一个测试
-            if (isProductionTestRunning) {
-                qDebug() << "LCD测试失败确认,延迟2秒后继续下一个测试";
-                qDebug() << "当前产测状态:" << isProductionTestRunning << "当前测试步骤:" << currentTestStep;
-                
-                // 延迟2秒确保LCD完全关闭,然后继续下一个测试
-                QTimer::singleShot(2000, this, [this]() {
-                    if (isProductionTestRunning) {
-                        skipToNextEnabledTest();
-                    }
-                });
-            }
-        }
-        
-    } else if (msgBox.clickedButton() == retestButton) {
+            QTimer::singleShot(2000, this, [this]() {
+                if (isProductionTestRunning) {
+                    skipToNextEnabledTest();
+                }
+            });
+        } else if (msgBox.clickedButton() == retestButton) {
         // 重新测试LCD
         qDebug() << "用户选择重新测试LCD";
         ui->statusbar->showMessage("重新开始LCD测试", 2000);
@@ -1348,7 +1112,7 @@ void MainWindow::showLcdTestConfirmDialog()
         // 重置LCD测试状态
         lcdTestPopupShown = false;
         isWaitingForUserConfirm = false;
-        currentLcdColor = 1; // 设置为1,从红色开始重新测试
+        currentLcdColor = 1;
         
         // 重新开始LCD测试
             // 检查LCD测试是否启用
@@ -1363,8 +1127,7 @@ void MainWindow::showLcdTestConfirmDialog()
         return; // 直接返回,不继续后续流程
     }
     
-    // 用户确认完成,马达测试已在上面的按钮处理中启动
-    qDebug() << "用户确认完成,马达测试已启动";
+    qDebug() << "LCD测试确认流程结束";
 }
 
 // 显示马达测试确认弹窗
@@ -2413,17 +2176,20 @@ QString MainWindow::saveTestRecord()
         dir.mkpath(saveDir);
     }
 
-    QString csvFileName = "产测记录.csv";
-    QString csvFilePath = saveDir + "/" + csvFileName;
+    const QString macTag = macTagForFilename(productionDeviceMac);
+    const QString timeTag = endTime.toString("yyyyMMdd_hhmmss_zzz");
 
-    bool isNewFile = !QFile::exists(csvFilePath);
+    const QString csvFileName = QStringLiteral("产测记录.csv");
+    const QString csvFilePath = saveDir + "/" + csvFileName;
 
     const QString header =
-        "开始时间,结束时间,测试耗时,软件版本,LCD测试,触控测试,亮度测试,马达测试,按键测试,功耗测试,录音测试,电池测试,G-sensor测试,漏光测试,蓝牙测试,SE芯片测试,GPS测试,整体结果\n";
+        "开始时间,结束时间,设备MAC,测试耗时,软件版本,LCD测试,触控测试,亮度测试,马达测试,按键测试,功耗测试,录音测试,电池测试,G-sensor测试,漏光测试,蓝牙测试,SE芯片测试,GPS测试,整体结果\n";
 
-    QString newDataLine = QString("%1,%2,%3,%4,%5,%6,%7,%8,%9,%10,%11,%12,%13,%14,%15,%16,%17,%18\n")
+    const QString macCol = macForCsvColumn(productionDeviceMac);
+    QString newDataLine = QString("%1,%2,%3,%4,%5,%6,%7,%8,%9,%10,%11,%12,%13,%14,%15,%16,%17,%18,%19\n")
                               .arg(startTimeStr)
                               .arg(endTimeStr)
+                              .arg(macCol)
                               .arg(durationStr)
                               .arg(ver.isEmpty() ? "未获取" : ver)
                               .arg(lcdResult)
@@ -2441,8 +2207,10 @@ QString MainWindow::saveTestRecord()
                               .arg(gpsResult)
                               .arg(overallResult);
 
+    const bool needHeader = !QFile::exists(csvFilePath) || QFileInfo(csvFilePath).size() == 0;
+
     QFile csvFile(csvFilePath);
-    if (!csvFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) {
+    if (!csvFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
         QMessageBox::warning(this, "保存失败",
                              QString("无法写入测试记录文件:\n%1\n错误:%2")
                                  .arg(csvFilePath)
@@ -2450,13 +2218,13 @@ QString MainWindow::saveTestRecord()
         return QString();
     }
 
-    if (isNewFile) {
+    if (needHeader) {
         csvFile.write(header.toLocal8Bit());
     }
     csvFile.write(newDataLine.toLocal8Bit());
     csvFile.close();
 
-    qDebug() << "测试记录已追加保存到:" << csvFilePath;
+    qDebug() << "测试记录已追加到:" << csvFilePath;
 
     ui->statusbar->showMessage(QString("测试记录已保存: %1").arg(csvFileName), 3000);
     
@@ -2476,7 +2244,12 @@ QString MainWindow::saveTestRecord()
         
         testLogStream->flush();
     }
-    closeTestLogFile();
+    const QString logsDirForRename = appPath + "/产测记录/logs";
+    QString finalLogPath = logsDirForRename + "/" + timeTag + "_" + macTag + ".log";
+    for (int dup = 1; QFile::exists(finalLogPath) && dup < 100; ++dup) {
+        finalLogPath = logsDirForRename + "/" + timeTag + "_" + macTag + "_" + QString::number(dup) + ".log";
+    }
+    closeTestLogFile(finalLogPath);
     
     // 保存UI日志到独立文件(如果有效)
     saveRecvTextEditToLog();
@@ -2493,55 +2266,34 @@ QString MainWindow::saveTestRecord()
 void MainWindow::parseWstpPrintData(const QString& data)
 {
     qDebug() << "检测到wstp_print格式数据:" << data.trimmed();
-    
-    // 解析BTMAC地址
-    // 格式:^^^^ BTMAC=XX:XX:XX:XX:XX:XX ^^^^
-    QRegExp btmacPattern("\\^\\^\\^\\^ BTMAC=([0-9A-Fa-f:]{17}) \\^\\^\\^\\^");
-    if (btmacPattern.indexIn(data) != -1) {
-        QString btmac = btmacPattern.cap(1);
-        qDebug() << "解析到BTMAC地址:" << btmac;
-        
-        // 这里可以将BTMAC地址填充到相应的文本框
-        // 如果有专门的BTMAC文本框,可以这样设置:
-        // ui->btmacLineEdit->setText(btmac);
-        
-        // 暂时显示在状态栏
-        ui->statusbar->showMessage(QString("检测到蓝牙MAC地址: %1").arg(btmac), 3000);
-    }
-    
-    // 解析CyweeChipInfo
-    // 格式:^^^^ CyweeChipInfo=XXXXXX ^^^^
-    QRegExp chipinfoPattern("\\^\\^\\^\\^ CyweeChipInfo=([^\\s\\^]+)");
-    if (chipinfoPattern.indexIn(data) != -1) {
-        QString chipinfo = chipinfoPattern.cap(1);
-        qDebug() << "解析到CyweeChipInfo:" << chipinfo;
-        
-        // 这里可以将芯片信息填充到相应的文本框
-        // 如果有专门的芯片信息文本框,可以这样设置:
-        // ui->chipinfoLineEdit->setText(chipinfo);
-        
-        // 暂时显示在状态栏
-        ui->statusbar->showMessage(QString("检测到芯片信息: %1").arg(chipinfo), 3000);
-    }
-    
-    // 完整的数据格式示例:
-    // wstp_print("^^^^ BTMAC=%s ^^^^ CyweeChipInfo=%s\n",btaddr_str,chipinfo);
-    // 实际输出可能是:^^^^ BTMAC=AA:BB:CC:DD:EE:FF ^^^^ CyweeChipInfo=MSA310
-    
-    // 如果需要同时解析两个值的完整格式
+
+    QString btmac;
+    bool fullMatched = false;
     QRegExp fullPattern("\\^\\^\\^\\^ BTMAC=([0-9A-Fa-f:]{17}) \\^\\^\\^\\^ CyweeChipInfo=([^\\s\\^\\n]+)");
     if (fullPattern.indexIn(data) != -1) {
-        QString btmac = fullPattern.cap(1);
-        QString chipinfo = fullPattern.cap(2);
-        
+        fullMatched = true;
+        btmac = fullPattern.cap(1);
+        const QString chipinfo = fullPattern.cap(2);
         qDebug() << "完整解析 - BTMAC:" << btmac << ", CyweeChipInfo:" << chipinfo;
-        
-        // 可以在这里将信息填充到对应的UI控件
-        // 例如:
-        // ui->btmacLineEdit->setText(btmac);
-        // ui->chipinfoLineEdit->setText(chipinfo);
-        
         ui->statusbar->showMessage(QString("设备信息 - MAC: %1, 芯片: %2").arg(btmac, chipinfo), 5000);
+    } else {
+        QRegExp btmacPattern("\\^\\^\\^\\^ BTMAC=([0-9A-Fa-f:]{17}) \\^\\^\\^\\^");
+        if (btmacPattern.indexIn(data) != -1) {
+            btmac = btmacPattern.cap(1);
+            qDebug() << "解析到BTMAC地址:" << btmac;
+            ui->statusbar->showMessage(QString("检测到蓝牙MAC地址: %1").arg(btmac), 3000);
+        }
+    }
+
+    if (!btmac.isEmpty()) {
+        productionDeviceMac = btmac.toUpper();
+    }
+
+    QRegExp chipinfoPattern("\\^\\^\\^\\^ CyweeChipInfo=([^\\s\\^]+)");
+    if (chipinfoPattern.indexIn(data) != -1 && !fullMatched) {
+        const QString chipinfo = chipinfoPattern.cap(1);
+        qDebug() << "解析到CyweeChipInfo:" << chipinfo;
+        ui->statusbar->showMessage(QString("检测到芯片信息: %1").arg(chipinfo), 3000);
     }
 }
 
@@ -2564,7 +2316,7 @@ void MainWindow::on_openRecordsFolderButton_clicked()
     if (success) {
         qDebug() << "成功打开文件夹:" << saveDir;
         ui->statusbar->showMessage("已打开产测记录文件夹", 2000);
-            } else {
+    } else {
         qDebug() << "打开文件夹失败:" << saveDir;
         QMessageBox::warning(this, "打开失败", 
             QString("无法打开文件夹:\n%1\n请检查路径是否存在或权限是否足够").arg(saveDir));
@@ -2617,7 +2369,8 @@ void MainWindow::on_openButton_2_clicked()
     
     // 在开始新测试前,尽量保存当前UI日志(如果有内容)
     saveRecvTextEditToLog();
-    
+    productionDeviceMac.clear();
+
     // 创建测试日志文件
     createTestLogFile();
     
@@ -2662,8 +2415,8 @@ void MainWindow::on_openButton_2_clicked()
     
     ui->statusbar->showMessage("开始产测流程...", 2000);
     qDebug() << "=== 开始产测流程 ===";
-    qDebug() << "流程: 产测开启(AT^FACTORY=1) → 设备重启 → … → 全部完成后弹窗确认 → AT^POWEROFF(关机)";
-    qDebug() << "LCDæ\8c\87令æ\98 å°\84: è¿\9bå\85¥=AT^LCDTEST=1, çº¢è\89²=AT^LCDTEST=6, ç»¿è\89²=AT^LCDTEST=3, è\93\9dè\89²=AT^LCDTEST=4, é\80\80å\87º=AT^LCDTEST=2";
+    qDebug() << "流程: 产测开启(AT^FACTORY=1) → 设备重启 → … → 全部完成后弹窗确认 → AT^RESTORE(恢复出厂) → AT^POWEROFF(关机)";
+    qDebug() << "LCDæµ\8bè¯\95: ä»\85å\8f\91é\80\81 AT^LCDTEST=1";
     
     // 发送产测开启指令,等待工厂模式确认
     qDebug() << "Step 1: 发送产测开启指令";
@@ -4332,8 +4085,8 @@ void MainWindow::onTestTimeout()
         // 先发送停止指令,然后重新开始测试
         qDebug() << "重试前发送停止指令";
         serial->write("AT^VIBRATORTIMER=0\r\n");  // 停止马达
-        serial->write("AT^LCDTEST=2\r\n");        // 退出LCD测试
-        
+        // LCD 产测仅使用 AT^LCDTEST=1,不再发 LCDTEST=2 等
+
         // 延迟500ms后重新开始测试
         QTimer::singleShot(500, this, [this, testDescription]() {
             qDebug() << "停止指令已发送,开始重试" << testDescription;
@@ -4795,38 +4548,18 @@ void MainWindow::on_getVersionInfoButton_clicked()
     startVersionInfoFetch();
 }
 
-// å\8e\8bå\8a\9bæµ\8bè¯\95æ\8c\89é\92®ç\82¹å\87»äº\8bä»¶
+// å\8e\9fã\80\8cå\8e\8bå\8a\9bæµ\8bè¯\95ã\80\8dæ\8c\89é\92®ï¼\9aå\8f\91é\80\81å\85³æ\9cºæ\8c\87令 AT^POWEROFF
 void MainWindow::on_pushButtonStressTest_clicked()
 {
-    // 检查串口是否已打开
-    if (!serial->isOpen()) {
-        QMessageBox::warning(this, "警告", "请先打开串口连接");
-        return;
-    }
-    
-    // 从配置管理器获取压力测试指令
-    QString stressTestCmd = configManager.getStressTestCommand();
-    
-    if (stressTestCmd.isEmpty()) {
-        QMessageBox::warning(this, "警告", "压力测试指令未配置");
-        qDebug() << "压力测试指令为空,无法执行";
+    if (!serial || !serial->isOpen()) {
+        QMessageBox::warning(this, "关机", "请先打开串口后再发送关机指令");
         return;
     }
-    
-    // 确保指令以\r\n结尾
-    if (!stressTestCmd.endsWith("\r\n")) {
-        stressTestCmd += "\r\n";
-    }
-    
-    // 发送压力测试指令
-    serial->write(stressTestCmd.toUtf8());
-    qDebug() << "发送压力测试指令:" << stressTestCmd.trimmed();
-    
-    // 在日志中记录
-    appendToLogFile(QString("=== 发送压力测试指令: %1 ===\n").arg(stressTestCmd.trimmed()));
-    
-    // 状态栏提示
-    ui->statusbar->showMessage("已发送压力测试指令", 3000);
+    ui->recvTextEdit->append(">>> 发送指令: AT^POWEROFF (手动关机)");
+    serial->write("AT^POWEROFF\r\n");
+    qDebug() << "手动发送关机指令: AT^POWEROFF";
+    ui->statusbar->showMessage("已发送关机指令 AT^POWEROFF", 3000);
+    appendToLogFile("=== 发送关机指令: AT^POWEROFF ===\n");
 }
 
 // 保存测试参数到settings.json
@@ -5178,11 +4911,11 @@ void MainWindow::saveRecvTextEditToLog()
         dir.mkpath(logsDir);
     }
     
-    // 生成日志文件名
     QDateTime now = QDateTime::currentDateTime();
+    const QString macTag = macTagForFilename(productionDeviceMac);
     QString fileName = QString("%1_%2_UI日志.log")
-                       .arg(now.toString("yyyyMMdd"))
-                       .arg(now.toString("hhmmss"));
+                       .arg(now.toString("yyyyMMdd_hhmmss"))
+                       .arg(macTag);
     
     QString filePath = logsDir + "/" + fileName;
     
@@ -5207,8 +4940,8 @@ void MainWindow::saveRecvTextEditToLog()
     if (!fullLogContent.trimmed().isEmpty()) {
         // 生成完整日志文件名(加full后缀)
         QString fullFileName = QString("%1_%2_UI日志full.log")
-                               .arg(now.toString("yyyyMMdd"))
-                               .arg(now.toString("hhmmss"));
+                               .arg(now.toString("yyyyMMdd_hhmmss"))
+                               .arg(macTag);
         
         QString fullFilePath = logsDir + "/" + fullFileName;
         
@@ -5248,16 +4981,14 @@ void MainWindow::createTestLogFile()
         dir.mkpath(logsDir);
     }
     
-    // 生成文件名:yyyymmdd_hhmmss.log
-    QString fileName = QString("%1_%2.log")
-                       .arg(now.toString("yyyyMMdd"))
-                       .arg(now.toString("hhmmss"));
-    
+    // 临时文件名,结束保存时再重命名为 时间_MAC.log
+    QString fileName = QString("%1_pending.log").arg(now.toString("yyyyMMdd_hhmmss"));
+
     testLogFilePath = logsDir + "/" + fileName;
-    
+
     // 创建并打开日志文件
     testLogFile = new QFile(testLogFilePath);
-    if (!testLogFile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) {
+    if (!testLogFile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
         qDebug() << "无法创建日志文件:" << testLogFilePath << "错误:" << testLogFile->errorString();
         delete testLogFile;
         testLogFile = nullptr;
@@ -5293,14 +5024,16 @@ void MainWindow::appendToLogFile(const QString& text)
     }
 }
 
-// 关闭测试日志文件
-void MainWindow::closeTestLogFile()
+// 关闭测试日志文件;renameToPath 非空且原路径存在时,关闭后重命名为最终路径
+void MainWindow::closeTestLogFile(const QString &renameToPath)
 {
+    const QString oldPath = testLogFilePath;
+
     if (testLogStream) {
         delete testLogStream;
         testLogStream = nullptr;
     }
-    
+
     if (testLogFile) {
         if (testLogFile->isOpen()) {
             testLogFile->close();
@@ -5308,8 +5041,21 @@ void MainWindow::closeTestLogFile()
         delete testLogFile;
         testLogFile = nullptr;
     }
-    
-    testLogFilePath = "";
+
+    testLogFilePath.clear();
+
+    if (!renameToPath.isEmpty() && !oldPath.isEmpty() && QFile::exists(oldPath)) {
+        QFileInfo fi(renameToPath);
+        QDir().mkpath(fi.absolutePath());
+        if (QFile::exists(renameToPath)) {
+            QFile::remove(renameToPath);
+        }
+        if (!QFile::rename(oldPath, renameToPath)) {
+            qDebug() << "测试日志重命名失败:" << oldPath << "->" << renameToPath;
+        } else {
+            qDebug() << "测试日志已重命名为:" << renameToPath;
+        }
+    }
 }
 
 // 使用设备信息重命名日志文件
index 91e1042..3215a5a 100644 (file)
@@ -55,8 +55,7 @@ private slots:
     
     // 产测相关槽函数
     void on_ProductionTestButton_clicked(); // 开始产测
-    void performLcdTest();                  // LCD测试
-    void performLcdColorTest();             // LCD颜色测试
+    void performLcdTest();                  // LCD测试(仅 AT^LCDTEST=1)
     void performMotorTest();                // 马达测试
     void performMotorTestContinue();        // 继续马达测试(LCD关闭后调用)
     void onLcdTestTimer();                  // LCD测试定时器
@@ -107,7 +106,7 @@ private slots:
     // 日志记录相关函数
     void createTestLogFile(); // 创建测试日志文件
     void appendToLogFile(const QString& text); // 追加内容到日志文件(同时显示到recvTextEdit)
-    void closeTestLogFile(); // 关闭测试日志文件
+    void closeTestLogFile(const QString &renameToPath = QString()); // 关闭测试日志文件;非空则关闭后重命名
     void renameLogFileWithDeviceInfo(); // 使用设备信息重命名日志文件
     void on_openButton_4_clicked();
 
@@ -123,7 +122,7 @@ private slots:
     // 版本信息获取按钮
     void on_getVersionInfoButton_clicked();
     
-    // å\8e\8bå\8a\9bæµ\8bè¯\95æ\8c\89é\92®
+    // å\85³æ\9cºæ\8c\89é\92®ï¼\88ç\95\8cé\9d¢å\8e\9fã\80\8cå\8e\8bå\8a\9bæµ\8bè¯\95ã\80\8dæ§½å\90\8dæ\9cªæ\94¹ï¼\8cé\81¿å\85\8dç ´å\9d\8f uic è\87ªå\8a¨è¿\9eæ\8e¥ï¼\89
     void on_pushButtonStressTest_clicked();
 
 private:
@@ -181,6 +180,7 @@ private:
     QFile *testLogFile;                 // 测试日志文件对象
     QTextStream *testLogStream;         // 测试日志文件流
     QString testLogFilePath;            // 测试日志文件路径
+    QString productionDeviceMac;        // 设备蓝牙 MAC(wstp_print 解析),用于 CSV/文件名
     
     // 配置管理
     ConfigManager configManager;       // 配置管理器(不使用指针,直接作为成员)
index 4d0cd0d..2381a98 100644 (file)
             </property>
             <property name="styleSheet">
              <string notr="true">QPushButton { 
-background-color: #ff0000; 
+background-color: #C62828; 
 color: white; 
 border-radius: 4px; 
 font-weight: bold; 
 }
 QPushButton:hover { 
-background-color: #F57C00; 
+background-color: #B71C1C; 
 }</string>
             </property>
             <property name="text">
-             <string>å\8e\8bå\8a\9bæµ\8bè¯\95</string>
+             <string>å\85³æ\9cº</string>
             </property>
            </widget>
           </item>