完成框架目录和模块重构;新增核心、单例、工具、加密及框架 SDK;统一任务、相机和 RPC 接口,并增加离线检测、相机标定、备份恢复、版本管理、崩溃守护和心跳监控功能。
328 lines
10 KiB
C++
328 lines
10 KiB
C++
#include <eui_tools/sql/qSqlBase.h>
|
|
#pragma once
|
|
|
|
#pragma once
|
|
#include <QString>
|
|
#include <QDateTime>
|
|
#include <QJsonObject>
|
|
#include <QJsonArray>
|
|
#include <QJsonDocument>
|
|
#include <vector>
|
|
#include <map>
|
|
|
|
// 界面上运行时数据缓存
|
|
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<QString, int>& defects)
|
|
{
|
|
return set(table, className, okCount, ngCount, defects, {});
|
|
}
|
|
bool set(Table table,
|
|
const QString& className,
|
|
const int& okCount,
|
|
const int& ngCount,
|
|
const std::map<std::string, int>& defects)
|
|
{
|
|
QMap<QString, int> 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<QString, int>& defects,
|
|
const QMap<QString, QMap<int, int>>& 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<std::string, int>& defects,
|
|
const std::map<std::string, std::map<int, int>>& defectsByHour)
|
|
{
|
|
QMap<QString, int> qDefects = toQMap(defects);
|
|
QMap<QString, QMap<int, int>> qDefectsByHour = toHourQMap(defectsByHour);
|
|
return set(table, className, okCount, ngCount, qDefects, qDefectsByHour);
|
|
}
|
|
|
|
// 读取
|
|
bool get(Table table,
|
|
const QString& className,
|
|
int& okCount,
|
|
int& ngCount,
|
|
QMap<QString, int>& defects)
|
|
{
|
|
QMap<QString, QMap<int, int>> defectsByHour;
|
|
return get(table, className, okCount, ngCount, defects, defectsByHour);
|
|
}
|
|
bool get(Table table,
|
|
const QString& className,
|
|
int& okCount,
|
|
int& ngCount,
|
|
std::map<std::string, int>& defects)
|
|
{
|
|
QMap<QString, int> qDefects;
|
|
QMap<QString, QMap<int, int>> 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<QString, int>& defects,
|
|
QMap<QString, QMap<int, int>>& 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<std::string, int>& defects,
|
|
std::map<std::string, std::map<int, int>>& defectsByHour)
|
|
{
|
|
QMap<QString, int> qDefects;
|
|
QMap<QString, QMap<int, int>> 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<QString, int>& 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<QString, int> deserializeDefects(const QString& json) {
|
|
QMap<QString, int> 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<QString, QMap<int, int>>& 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<QString, QMap<int, int>> deserializeDefectsByHour(const QString& json) {
|
|
QMap<QString, QMap<int, int>> 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<int, int> 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<QString, int> toQMap(const std::map<std::string, int>& in) {
|
|
QMap<QString, int> out;
|
|
for (const auto& [k, v] : in) {
|
|
out[QString::fromStdString(k)] = v;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
// QMap -> std::map
|
|
std::map<std::string, int> toStdMap(const QMap<QString, int>& in) {
|
|
std::map<std::string, int> out;
|
|
for (auto it = in.begin(); it != in.end(); ++it) {
|
|
out[it.key().toStdString()] = it.value();
|
|
}
|
|
return out;
|
|
}
|
|
|
|
// std::map -> QMap
|
|
QMap<QString, QMap<int, int>> toHourQMap(const std::map<std::string, std::map<int, int>>& in) {
|
|
QMap<QString, QMap<int, int>> out;
|
|
for (const auto& [k, v] : in) {
|
|
QMap<int, int> hourMap;
|
|
for (const auto& [hour, count] : v) {
|
|
hourMap[hour] = count;
|
|
}
|
|
out[QString::fromStdString(k)] = hourMap;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
// QMap -> std::map
|
|
std::map<std::string, std::map<int, int>> toHourStdMap(const QMap<QString, QMap<int, int>>& in) {
|
|
std::map<std::string, std::map<int, int>> out;
|
|
for (auto it = in.begin(); it != in.end(); ++it) {
|
|
std::map<int, int> 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;
|
|
}
|
|
};
|
|
|