稳定版本备份

This commit is contained in:
2025-08-25 15:53:05 +08:00
parent 53178ddd9a
commit aae60af637
53 changed files with 1197 additions and 1612 deletions
+153 -160
View File
@@ -24,16 +24,20 @@
#include <fstream>
#include <qelapsedtimer.h>
#include <QQueue>
#include <quuid.h>
#include <global.h>
#include <qthread.h>
class SQLiteDB {
public:
SQLiteDB(const QString& dbPath, const QString& dbName)
: m_dbName(dbName), m_dbPath(dbPath) {
QSqlDatabase db;
SQLiteDB(const QString& dbPath)
: dbPath(dbPath){
connect();
}
~SQLiteDB() { disconnect(); };
// 执行无返回值的SQL语句(如插入、删除、更新)
bool execute(const QString& queryStr, const QVariantList& args = {}) {
QSqlQuery query;
QSqlQuery query(db);
query.prepare(queryStr);
for (int i = 0; i < args.size(); ++i) {
@@ -50,7 +54,7 @@ public:
// 查询数据,返回结果集
QList<QMap<QString, QVariant>> query(const QString& queryStr, const QVariantList& args = {}) {
QList<QMap<QString, QVariant>> results;
QSqlQuery query;
QSqlQuery query(db);
query.prepare(queryStr);
for (int i = 0; i < args.size(); ++i) {
@@ -75,7 +79,7 @@ public:
}
// 检查数据库是否已连接
bool isConnected() const {
return m_db.isOpen();
return db.isOpen();
}
////////////////BASE//////////////////////
bool createTable(const QString& tableName, const QList<std::pair<QString, QString>>& columns) {
@@ -93,7 +97,7 @@ public:
QString sql = QString("CREATE TABLE IF NOT EXISTS \"%1\" (%2)")
.arg(tableName)
.arg(columnDefinitions.join(", "));
QSqlQuery query(m_db);
QSqlQuery query(db);
bool res = query.exec(sql);
return res;
}
@@ -101,7 +105,7 @@ public:
std::vector<QString> tables;
// 查询所有表名,排除sqlite系统表
QString sql = "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%';";
QSqlQuery query(m_db);
QSqlQuery query(db);
if (!query.exec(sql)) {
qDebug() << "getTables failed:" << query.lastError().text();
return tables;
@@ -126,7 +130,7 @@ public:
// 构造 SQL 语句
QString sql = QString("ALTER TABLE \"%1\" ADD COLUMN \"%2\" %3").arg(tableName, columnName, columnType);
QSqlQuery query(m_db);
QSqlQuery query(db);
query.prepare(sql);
// 执行 SQL 语句
@@ -177,10 +181,10 @@ public:
qDebug() << "Generated SQL: " << sql;
QSqlQuery query(m_db);
QSqlQuery query(db);
// 检查数据库连接
if (!m_db.isOpen()) {
if (!db.isOpen()) {
qDebug() << "Database is not open!";
return false;
}
@@ -222,10 +226,10 @@ public:
qDebug() << "Generated SQL: " << sql;
QSqlQuery query(m_db);
QSqlQuery query(db);
// 检查数据库连接
if (!m_db.isOpen()) {
if (!db.isOpen()) {
qDebug() << "Database is not open!";
return false;
}
@@ -256,7 +260,7 @@ public:
.arg(tableName)
.arg(whereClauses.join(" AND "));
QSqlQuery query(m_db);
QSqlQuery query(db);
query.prepare(sql);
// 绑定条件参数
@@ -293,10 +297,10 @@ public:
qDebug() << "Generated SQL: " << sql;
QSqlQuery query(m_db);
QSqlQuery query(db);
// 检查数据库连接
if (!m_db.isOpen()) {
if (!db.isOpen()) {
qDebug() << "Database is not open!";
return {};
}
@@ -332,7 +336,7 @@ public:
// 查询表中的所有数据
QString csvFileName = filePath;
QString sql = QString("SELECT * FROM \"%1\"").arg(tableName);
QSqlQuery query(m_db);
QSqlQuery query(db);
if (!query.exec(sql)) {
qCritical() << "Query execution failed: " << query.lastError().text();
@@ -386,23 +390,23 @@ public:
private:
bool connect() {
m_connectionName = QUuid::createUuid().toString();
// 检查数据库文件是否存在
if (!QFile::exists(m_dbPath + m_dbName + ".db")) {
QDir().mkpath(m_dbPath);
qDebug() << "Database file does not exist. Creating a new database:" << m_dbName;
if (!QFile::exists(dbPath)) {
QFileInfo fi(dbPath);
QDir().mkpath(fi.absolutePath());
qDebug() << "Database file does not exist. Creating a new database:" << dbPath;
}
QCoreApplication::addLibraryPath("./");
// 添加 SQLite 数据库驱动
m_db = QSqlDatabase::addDatabase("QSQLITE");
m_db.setDatabaseName(m_dbPath + m_dbName + ".db");
db = QSqlDatabase::addDatabase("QSQLITE", m_connectionName);
db.setDatabaseName(dbPath);
// 打开数据库
if (!m_db.open()) {
qCritical() << "Failed to open or create database:" << m_db.lastError().text();
if (!db.open()) {
qCritical() << "Failed to open or create database:" << db.lastError().text();
return false;
}
qDebug() << "Connected to SQLite database:" << m_dbPath + m_dbName;
qDebug() << "Connected to SQLite database:" << dbPath;
createTable("setting",
{
{"id","INTEGER PRIMARY KEY AUTOINCREMENT"} ,
@@ -411,23 +415,20 @@ private:
}
// 关闭数据库连接
void disconnect() {
if (m_db.isOpen()) {
m_db.close();
QSqlDatabase::removeDatabase(m_connectionName);
if (db.isOpen()) {
db.close();
qDebug() << "Database closed.";
}
}
QString m_dbName;
QString m_dbPath;
QSqlDatabase m_db;
QString m_connectionName;
QString dbPath;
};
class CsvWriter
{
class CsvWriter : public QThread{
public:
CsvWriter(SQLiteDB* database_ptr = nullptr)
{
try
{
CsvWriter(){
try{
m_json = readJsonFromPath("./sqldrivers/sqliteCfg.json");
for (auto& data : m_json["数据列表"]) {
db_InitColumns.append({ QString::fromStdString(data),"TEXT" });
@@ -446,115 +447,36 @@ public:
isNgDepends.push_back(QString::fromStdString(data));
}
}
catch (const std::exception&)
{
catch (const std::exception&){
std::cerr << "readJsonFromPath error" << std::endl;
}
init(database_ptr);
init();
}
~CsvWriter()
{
~CsvWriter(){
//stopAutoExport();
}
std::map<QString, QString>csvAndChartLink;
bool addtData(const QString& snCode, const std::map<QString, QVariant>& data) {
try {
if (snCode.isEmpty()) {
qWarning() << "addtData: snCode is empty.";
return false;
}
if (data.empty()) {
qWarning() << "addtData: data is empty.";
return false;
}
std::lock_guard<std::mutex> locker(_mutex);
QString currentProcessCsvName = getCurrentProcessCsvName();
if (currentProcessCsvName != currentProcessCsvNameCache) {
if (!_db->createTable(currentProcessCsvName, db_InitColumns)) {
qWarning() << "addtData: Failed to create table:" << currentProcessCsvName;
return false;
}
currentProcessCsvNameCache = currentProcessCsvName;
}
// 获取当前表的所有列名
QSqlQuery colQuery;
QString colSql = QString("PRAGMA table_info(\"%1\")").arg(currentProcessCsvName);
QList<QString> tableColumns;
if (colQuery.exec(colSql)) {
while (colQuery.next()) {
tableColumns.append(colQuery.value(1).toString());
}
}
// 检查 data 中的 key 是否在表结构中,不在则新增列
for (const auto& kv : data) {
if (!tableColumns.contains(kv.first)) {
// 默认新增为 TEXT 类型
if (!_db->addColumn(currentProcessCsvName, kv.first, "TEXT")) {
qWarning() << "addtData: Failed to add column:" << kv.first << "to table:" << currentProcessCsvName;
// 可选择 return false 或继续
}
}
}
auto res = _db->_search(currentProcessCsvName, {}, { {"条码",snCode} });
QString nowTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz"); // 精度提升到毫秒
bool opResult = false;
if (res.empty()) {
auto lastRes = _db->_search(getLastProcessCsvName(), {}, { {"条码",snCode} });
if (lastRes.empty()) {
// 插入新数据
std::map<QString, QVariant> insertData = data;
insertData["条码"] = snCode;
insertData["创建时间"] = nowTime;
insertData["修改时间"] = nowTime;
opResult = _db->_insert(currentProcessCsvName, insertData);
if (!opResult) {
qWarning() << "addtData: Insert failed for table:" << currentProcessCsvName << "snCode:" << snCode;
}
} else {
// 更新过去的数据
std::map<QString, QVariant> updateData = data;
updateData["修改时间"] = nowTime;
opResult = _db->_update(getLastProcessCsvName(), updateData, { {"条码",snCode} });
if (!opResult) {
qWarning() << "addtData: Update failed for table:" << getLastProcessCsvName() << "snCode:" << snCode;
}
}
} else {
// 更新当前数据
std::map<QString, QVariant> updateData = data;
updateData["修改时间"] = nowTime;
opResult = _db->_update(getCurrentProcessCsvName(), updateData, { {"条码",snCode} });
if (!opResult) {
qWarning() << "addtData: Update failed for table:" << getCurrentProcessCsvName() << "snCode:" << snCode;
}
}
if (timer.elapsed() > m_intervalMs) {
exportCsv();
timer.start();
}
return opResult;
} catch (const std::exception& ex) {
qCritical() << "addtData: Exception caught:" << ex.what();
return false;
} catch (...) {
qCritical() << "addtData: Unknown exception caught.";
return false;
void addData(QString snCode, std::map<QString, QVariant> data) {
if (snCode.isEmpty()) {
qWarning() << "addtData: snCode is empty.";
return;
}
if (data.empty()) {
qWarning() << "addtData: data is empty.";
return;
}
queue.enqueue(std::make_pair(snCode, data));
this->start();
}
bool isNewData(const QString& snCode) {
std::lock_guard<std::mutex> locker(_mutex);
auto res = _db->_search(getCurrentProcessCsvName(), {}, { {"条码",snCode} });
auto res = db->_search(getCurrentProcessCsvName(), {}, { {"条码",snCode} });
return res.empty();
}
bool isNgData(const QString& snCode) {
std::lock_guard<std::mutex> locker(_mutex);
auto res = _db->_search(getCurrentProcessCsvName(), {}, { {"条码",snCode} });
auto res = db->_search(getCurrentProcessCsvName(), {}, { {"条码",snCode} });
if (res.empty() == true)
return false;
for (auto& data : isNgDepends) {
@@ -563,11 +485,99 @@ public:
}
return false;
}
void run() override{
while (queue.size() > 0) {
auto val = queue.dequeue();
try {
auto snCode = val.first;
auto data = val.second;
QString currentProcessCsvName = getCurrentProcessCsvName();
if (currentProcessCsvName != currentProcessCsvNameCache) {
if (!db->createTable(currentProcessCsvName, db_InitColumns)) {
qWarning() << "addtData: Failed to create table:" << currentProcessCsvName;
return;
}
currentProcessCsvNameCache = currentProcessCsvName;
}
// 获取当前表的所有列名
QSqlQuery colQuery(db->db);
QString colSql = QString("PRAGMA table_info(\"%1\")").arg(currentProcessCsvName);
QList<QString> tableColumns;
if (colQuery.exec(colSql)) {
while (colQuery.next()) {
tableColumns.append(colQuery.value(1).toString());
}
}
// 检查 data 中的 key 是否在表结构中,不在则新增列
for (const auto& kv : data) {
if (!tableColumns.contains(kv.first)) {
// 默认新增为 TEXT 类型
if (!db->addColumn(currentProcessCsvName, kv.first, "TEXT")) {
qWarning() << "addtData: Failed to add column:" << kv.first << "to table:" << currentProcessCsvName;
// 可选择 return false 或继续
}
}
}
auto res = db->_search(currentProcessCsvName, {}, { {"条码",snCode} });
QString nowTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz"); // 精度提升到毫秒
bool opResult = false;
if (res.empty()) {
auto lastRes = db->_search(getLastProcessCsvName(), {}, { {"条码",snCode} });
if (lastRes.empty()) {
// 插入新数据
std::map<QString, QVariant> insertData = data;
insertData["条码"] = snCode;
insertData["创建时间"] = nowTime;
insertData["修改时间"] = nowTime;
opResult = db->_insert(currentProcessCsvName, insertData);
if (!opResult) {
qWarning() << "addtData: Insert failed for table:" << currentProcessCsvName << "snCode:" << snCode;
}
}
else {
// 更新过去的数据
std::map<QString, QVariant> updateData = data;
updateData["修改时间"] = nowTime;
opResult = db->_update(getLastProcessCsvName(), updateData, { {"条码",snCode} });
if (!opResult) {
qWarning() << "addtData: Update failed for table:" << getLastProcessCsvName() << "snCode:" << snCode;
}
}
}
else {
// 更新当前数据
std::map<QString, QVariant> updateData = data;
updateData["修改时间"] = nowTime;
opResult = db->_update(getCurrentProcessCsvName(), updateData, { {"条码",snCode} });
if (!opResult) {
qWarning() << "addtData: Update failed for table:" << getCurrentProcessCsvName() << "snCode:" << snCode;
}
}
//if (timer.elapsed() > m_intervalMs) {
// exportCsv();
// timer.start();
//}
}
catch (const std::exception& ex) {
qCritical() << "addtData: Exception caught:" << ex.what();
}
catch (...) {
qCritical() << "addtData: Unknown exception caught.";
}
}
}
private:
QQueue<std::pair<QString,std::map<QString, QVariant>>> queue;
std::vector<QString> isNgDepends;
QQueue<std::pair< QString, std::map<QString, QVariant>> > addDataCacheQueue;
std::mutex _mutex;
SQLiteDB* _db;
SQLiteDB* db;
int m_intervalMs = 10000;
QElapsedTimer timer;
QString currentProcessCsvNameCache;
@@ -579,36 +589,19 @@ private:
{"修改时间", "TEXT"},
{"CT", "TEXT"},
};
//void run()
//{
// init();
// while (m_running == true) {
// QThread::msleep(m_intervalMs);
// while (addDataCacheQueue.empty() == false)
// {
// auto data = addDataCacheQueue.dequeue();
// addtData(data.first, data.second);
// }
// exportCsv();
// }
// delete _db;
//}
void init(SQLiteDB* database_ptr = nullptr){
void init(){
std::lock_guard<std::mutex> locker(_mutex);
if (database_ptr == nullptr)
_db = new SQLiteDB("./sqlDatabse/", "database");
else
_db = database_ptr;
if (!_db->createTable(getLastProcessCsvName(), db_InitColumns)) {
db = new SQLiteDB(globalDatabasePth);
if (!db->createTable(getLastProcessCsvName(), db_InitColumns)) {
qDebug() << "Failed to create table " << getLastProcessCsvName();
}
currentProcessCsvNameCache = getCurrentProcessCsvName();
if (!_db->createTable(currentProcessCsvNameCache, db_InitColumns)) {
if (!db->createTable(currentProcessCsvNameCache, db_InitColumns)) {
qDebug() << "Failed to create table " << currentProcessCsvNameCache;
}
for (auto& data : db_newCol) {
_db->addColumn(getLastProcessCsvName(), data.first, data.second);
_db->addColumn(getCurrentProcessCsvName(), data.first, data.second);
db->addColumn(getLastProcessCsvName(), data.first, data.second);
db->addColumn(getCurrentProcessCsvName(), data.first, data.second);
}
timer.start();
}
@@ -676,12 +669,12 @@ private:
void exportCsv(){
//std::lock_guard<std::mutex> locker(_mutex);
QString name = getLastProcessCsvName();
_db->exportTableToCSV(name, "./csv/"+ name +".csv", _mutex);
db->exportTableToCSV(name, "./csv/"+ name +".csv", _mutex);
name = getCurrentProcessCsvName();
_db->exportTableToCSV(name, "./csv/" + name + ".csv", _mutex);
db->exportTableToCSV(name, "./csv/" + name + ".csv", _mutex);
QString currentProcessCsvName = getCurrentProcessCsvName();
if (currentProcessCsvName != currentProcessCsvNameCache)
if (!_db->createTable(currentProcessCsvName, db_InitColumns)) {
if (!db->createTable(currentProcessCsvName, db_InitColumns)) {
return;
}
else