#include #pragma once #pragma once #include #include #include #include #include #include #include // 界面上运行时数据缓存 class runtimeDataCacheStore { public: // 表枚举(统一管理) enum class Table { RuntimeCache,//运行时数据缓存 Statistics//统计数据缓存 }; explicit runtimeDataCacheStore(sqliteConnection* dbIn) : db(dbIn) { initAllTables(); } //设置 bool set(Table table, const QString& className, const int& okCount, const int& ngCount, const QMap& defects) { return set(table, className, okCount, ngCount, defects, {}); } bool set(Table table, const QString& className, const int& okCount, const int& ngCount, const std::map& defects) { QMap qDefects = toQMap(defects); return set(table, className, okCount, ngCount, qDefects, {}); } bool set(Table table, const QString& className, const int& okCount, const int& ngCount, const QMap& defects, const QMap>& defectsByHour) { QString tableName = getTableName(table); QString defectsJson = serializeDefects(defects); QString defectsByHourJson = serializeDefectsByHour(defectsByHour); QString sql = QString(R"( INSERT INTO %1 ( class_name, ok_count, ng_count, defects, defects_by_hour, update_time ) VALUES (?, ?, ?, ?, ?, ?) ON CONFLICT(class_name) DO UPDATE SET ok_count = excluded.ok_count, ng_count = excluded.ng_count, defects = excluded.defects, defects_by_hour = excluded.defects_by_hour, update_time = excluded.update_time; )").arg(tableName); return db->execute(sql, { className, okCount, ngCount, defectsJson, defectsByHourJson, QDateTime::currentSecsSinceEpoch() }); } bool set(Table table, const QString& className, const int& okCount, const int& ngCount, const std::map& defects, const std::map>& defectsByHour) { QMap qDefects = toQMap(defects); QMap> qDefectsByHour = toHourQMap(defectsByHour); return set(table, className, okCount, ngCount, qDefects, qDefectsByHour); } // 读取 bool get(Table table, const QString& className, int& okCount, int& ngCount, QMap& defects) { QMap> defectsByHour; return get(table, className, okCount, ngCount, defects, defectsByHour); } bool get(Table table, const QString& className, int& okCount, int& ngCount, std::map& defects) { QMap qDefects; QMap> qDefectsByHour; bool ret = get(table, className, okCount, ngCount, qDefects, qDefectsByHour); if (!ret) return false; defects = toStdMap(qDefects); return true; } bool get(Table table, const QString& className, int& okCount, int& ngCount, QMap& defects, QMap>& defectsByHour) { QString tableName = getTableName(table); auto results = db->_search( tableName, { "ok_count", "ng_count", "defects", "defects_by_hour" }, { {"class_name", className} } ); if (results.empty()) return false; const auto& row = results[0]; if (row.find("ok_count") != row.end()) okCount = row.at("ok_count").toInt(); if (row.find("ng_count") != row.end()) ngCount = row.at("ng_count").toInt(); if (row.find("defects") != row.end()) { QString defectsJson = row.at("defects").toString(); defects = deserializeDefects(defectsJson); } if (row.find("defects_by_hour") != row.end()) { QString defectsByHourJson = row.at("defects_by_hour").toString(); defectsByHour = deserializeDefectsByHour(defectsByHourJson); } return true; } bool get(Table table, const QString& className, int& okCount, int& ngCount, std::map& defects, std::map>& defectsByHour) { QMap qDefects; QMap> qDefectsByHour; bool ret = get(table, className, okCount, ngCount, qDefects, qDefectsByHour); if (!ret) return false; defects = toStdMap(qDefects); defectsByHour = toHourStdMap(qDefectsByHour); return true; } private: sqliteConnection* db = nullptr; // enum -> 表名映射(核心) QString getTableName(Table table) const { switch (table) { case Table::RuntimeCache: return "runtime_cache_hide";//运行时数据缓存 case Table::Statistics: return "statistics_cache_hide";//统计数据缓存 default: return "unknow_cache_hide"; } } // 初始化所有表 void initAllTables() { for (auto table : {Table::RuntimeCache, Table::Statistics }) { initTable(getTableName(table)); } } void initTable(const QString& tableName) { if (tableName == "unknow_cache_hide") { qCritical() << "Attempted to initialize unknown table: " << tableName; return; } db->createTable(tableName, { {"class_name", "TEXT PRIMARY KEY"}, {"ok_count", "INTEGER"}, {"ng_count", "INTEGER"}, {"defects", "TEXT"}, {"defects_by_hour", "TEXT"}, {"update_time", "INTEGER"} }); // 旧版本数据库可能缺少新列,CREATE TABLE IF NOT EXISTS 不会补列,需要显式迁移 ensureColumn(tableName, "defects_by_hour", "TEXT"); } void ensureColumn(const QString& tableName, const QString& columnName, const QString& columnType) { const auto columns = db->query(QString("PRAGMA table_info(%1)").arg(tableName)); for (const auto& column : columns) { if (column.value("name").toString() == columnName) return; } db->execute(QString("ALTER TABLE %1 ADD COLUMN %2 %3") .arg(tableName, columnName, columnType)); } // QMap -> JSON(更简洁版本) QString serializeDefects(const QMap& defects) { QJsonObject obj; for (auto it = defects.begin(); it != defects.end(); ++it) { obj[it.key()] = it.value(); } return QJsonDocument(obj).toJson(QJsonDocument::Compact); } // JSON -> QMap QMap deserializeDefects(const QString& json) { QMap result; QJsonDocument doc = QJsonDocument::fromJson(json.toUtf8()); if (!doc.isObject()) return result; QJsonObject obj = doc.object(); for (auto it = obj.begin(); it != obj.end(); ++it) { result[it.key()] = it.value().toInt(); } return result; } QString serializeDefectsByHour(const QMap>& defectsByHour) { QJsonObject obj; for (auto it = defectsByHour.begin(); it != defectsByHour.end(); ++it) { QJsonObject hourObj; const auto& hourMap = it.value(); for (auto hourIt = hourMap.begin(); hourIt != hourMap.end(); ++hourIt) { hourObj[QString::number(hourIt.key())] = hourIt.value(); } obj[it.key()] = hourObj; } return QJsonDocument(obj).toJson(QJsonDocument::Compact); } QMap> deserializeDefectsByHour(const QString& json) { QMap> result; QJsonDocument doc = QJsonDocument::fromJson(json.toUtf8()); if (!doc.isObject()) return result; QJsonObject obj = doc.object(); for (auto it = obj.begin(); it != obj.end(); ++it) { if (!it.value().isObject()) continue; QJsonObject hourObj = it.value().toObject(); QMap hourMap; for (auto hourIt = hourObj.begin(); hourIt != hourObj.end(); ++hourIt) { bool ok = false; const int hour = hourIt.key().toInt(&ok); if (ok) hourMap[hour] = hourIt.value().toInt(); } result[it.key()] = hourMap; } return result; } // std::map -> QMap QMap toQMap(const std::map& in) { QMap out; for (const auto& [k, v] : in) { out[QString::fromStdString(k)] = v; } return out; } // QMap -> std::map std::map toStdMap(const QMap& in) { std::map out; for (auto it = in.begin(); it != in.end(); ++it) { out[it.key().toStdString()] = it.value(); } return out; } // std::map -> QMap QMap> toHourQMap(const std::map>& in) { QMap> out; for (const auto& [k, v] : in) { QMap hourMap; for (const auto& [hour, count] : v) { hourMap[hour] = count; } out[QString::fromStdString(k)] = hourMap; } return out; } // QMap -> std::map std::map> toHourStdMap(const QMap>& in) { std::map> out; for (auto it = in.begin(); it != in.end(); ++it) { std::map hourMap; const auto& qHourMap = it.value(); for (auto hourIt = qHourMap.begin(); hourIt != qHourMap.end(); ++hourIt) { hourMap[hourIt.key()] = hourIt.value(); } out[it.key().toStdString()] = hourMap; } return out; } };