chenluhua1980
2025-11-11 93782ae523667cd742c5a99e8df9a34dc503523b
1.修复保存单条记录时未保存曲线数据的问题;
已修改3个文件
100 ■■■■■ 文件已修改
SourceCode/Bond/Servo/CMaster.cpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPageGlassList.cpp 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CPageGlassList.h 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CMaster.cpp
@@ -3195,7 +3195,7 @@
            auto& coolingTypes = dataTypes[EQ_ID_BAKE_COOLING];
            for (size_t i = 0; i < coolingTypes.size(); ++i) {
                m_pCollector->buffersSetChannelName(EQ_ID_VACUUMBAKE, i + 1, coolingTypes[i].c_str());
                m_pCollector->buffersSetChannelName(EQ_ID_BAKE_COOLING, i + 1, coolingTypes[i].c_str());
            }
        }
    }
SourceCode/Bond/Servo/CPageGlassList.cpp
@@ -13,6 +13,7 @@
#include <unordered_map>
#include <vector>
#include <string>
#include <algorithm>
#include "CProcessDataListDlg.h"
#define PAGE_SIZE                       50
@@ -1481,69 +1482,59 @@
            // 对每个机器生成表格
            for (const auto& machinePair : tempGlass.getAllSVData()) {
                int machineId = machinePair.first;
                const auto& dataByType = machinePair.second;
                CString machineName = CString(SERVO::CServoUtilsTool::getEqName(machineId).c_str());
                csvContent += _T("\n[") + machineName + _T("]\n");
                // 获取该机器的预定义列顺序
                auto columnOrder = getMachineColumnOrder(machineId);
                if (columnOrder.empty()) {
                    csvContent += _T("无预定义列配置\n");
                if (dataByType.empty()) {
                    csvContent += _T("No sensor data\n");
                    continue;
                }
                // 构建表头 - 直接使用中文列名
                CString header = _T("时间戳(ms),本地时间");
                auto columnOrder = getMachineColumnOrder(machineId, &dataByType);
                if (columnOrder.empty()) {
                    csvContent += _T("No exportable columns\n");
                    continue;
                }
                CString header = _T("Timestamp(ms),LocalTime");
                for (const auto& dataType : columnOrder) {
                    header += _T(",");
                    header += CString(dataType.c_str()); // 直接使用中文列名
                    header += CString(dataType.c_str());
                }
                header += _T("\n");
                csvContent += header;
                // 检查是否有数据
                if (machinePair.second.empty()) {
                    csvContent += _T("无传感器数据\n");
                auto baselineIt = std::find_if(columnOrder.begin(), columnOrder.end(),
                    [&](const std::string& type) {
                        auto dataIt = dataByType.find(type);
                        return dataIt != dataByType.end() && !dataIt->second.empty();
                    });
                if (baselineIt == columnOrder.end()) {
                    csvContent += _T("No usable time series\n");
                    continue;
                }
                // 使用第一个数据类型的时间序列作为基准
                const std::string& firstDataType = columnOrder[0];
                auto firstDataTypeIt = machinePair.second.find(firstDataType);
                if (firstDataTypeIt == machinePair.second.end() || firstDataTypeIt->second.empty()) {
                    csvContent += _T("无基准数据类型数据\n");
                    continue;
                }
                const auto& timeSeries = firstDataTypeIt->second;
                // 对于每个时间点,输出一行数据
                for (size_t i = 0; i < timeSeries.size(); i++) {
                const auto& timeSeries = dataByType.at(*baselineIt);
                for (size_t i = 0; i < timeSeries.size(); ++i) {
                    auto timestamp = timeSeries[i].timestamp;
                    // 时间戳(毫秒)
                    auto ms = timePointToMs(timestamp);
                    CString row;
                    row.Format(_T("%lld,"), ms);
                    // 本地时间字符串
                    CString localTime = CString(timePointToString(timestamp).c_str());
                    row += localTime;
                    // 按照预定义的列顺序输出数据
                    for (const auto& dataType : columnOrder) {
                        row += _T(",");
                        auto dataTypeIt = machinePair.second.find(dataType);
                        if (dataTypeIt != machinePair.second.end() && i < dataTypeIt->second.size()) {
                            // 直接按索引获取数据
                        auto dataTypeIt = dataByType.find(dataType);
                        if (dataTypeIt != dataByType.end() && i < dataTypeIt->second.size()) {
                            CString valueStr;
                            valueStr.Format(_T("%.3f"), dataTypeIt->second[i].value);
                            row += valueStr;
                        }
                        else {
                            // 理论上不应该发生,因为您说没有空值
                            row += _T("N/A");
                        }
                    }
@@ -1919,11 +1910,33 @@
}
// 获取机器预定义的列顺序
std::vector<std::string> CPageGlassList::getMachineColumnOrder(int machineId)
std::vector<std::string> CPageGlassList::getMachineColumnOrder(int machineId,
    const std::unordered_map<std::string, std::vector<SERVO::SVDataItem>>* actualData)
{
    std::vector<std::string> columnOrder;
    auto dataTypes = SERVO::CServoUtilsTool::getEqDataTypes();
    auto it = dataTypes.find(machineId);
    return it != dataTypes.end() ? it->second : std::vector<std::string>();
    if (actualData != nullptr) {
        if (it != dataTypes.end()) {
            for (const auto& name : it->second) {
                if (actualData->find(name) != actualData->end()) {
                    columnOrder.push_back(name);
                }
            }
        }
        for (const auto& kv : *actualData) {
            if (std::find(columnOrder.begin(), columnOrder.end(), kv.first) == columnOrder.end()) {
                columnOrder.push_back(kv.first);
            }
        }
        return columnOrder;
    }
    if (it != dataTypes.end()) {
        columnOrder = it->second;
    }
    return columnOrder;
}
// 时间戳转换为字符串
@@ -1953,13 +1966,25 @@
    for (const auto& machinePair : dataTypes) {
        int machineId = machinePair.first;
        const auto& dataTypeList = machinePair.second;
        std::vector<std::string> filteredTypes;
        if (machineId == EQ_ID_VACUUMBAKE || machineId == EQ_ID_BAKE_COOLING) {
            const char activePrefix = 'A';
            for (const auto& dataType : dataTypeList) {
                if (!dataType.empty() && dataType[0] == activePrefix) {
                    filteredTypes.push_back(dataType);
                }
            }
        }
        const auto& typeList = filteredTypes.empty() ? dataTypeList : filteredTypes;
        
        // 生成时间序列:从当前时间往前推10分钟,每1秒一个数据点
        auto now = std::chrono::system_clock::now();
        auto startTime = now - std::chrono::minutes(10);
        
        // 为每个数据类型生成模拟数据
        for (const auto& dataType : dataTypeList) {
        for (const auto& dataType : typeList) {
            std::vector<SERVO::SVDataItem> mockData;
            
            // 生成600个数据点(10分钟 * 60个点/分钟)
SourceCode/Bond/Servo/CPageGlassList.h
@@ -1,6 +1,7 @@
#pragma once
#include "CExpandableListCtrl.h"
#include "GlassLogDb.h"
#include <unordered_map>
// ====== 编译开关说明 ======
// USE_MOCK_SENSOR_DATA: 1=启用模拟传感器数据生成;0=使用真实数据
@@ -65,7 +66,7 @@
    void ExportBasicInfo(CString& csvContent, const GlassLogDb::Row& row);
    void ExportProcessParams(CString& csvContent, const GlassLogDb::Row& row);
    void ExportSensorData(CString& csvContent, const GlassLogDb::Row& row);
    static std::vector<std::string> getMachineColumnOrder(int machineId);
    static std::vector<std::string> getMachineColumnOrder(int machineId, const std::unordered_map<std::string, std::vector<SERVO::SVDataItem>>* actualData = nullptr);
    static std::string timePointToString(const std::chrono::system_clock::time_point& tp);
    static int64_t timePointToMs(const std::chrono::system_clock::time_point& tp);
    void GenerateMockSVData(SERVO::CGlass& glass);