695 lines
24 KiB
C++
695 lines
24 KiB
C++
#include <qfile.h>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <mutex>
|
|
#include <qdatetime.h>
|
|
#include <memory>
|
|
#include <qtextstream.h>
|
|
#include <QtSql/QSqlDatabase>
|
|
#include <QtSql/QSqlQuery>
|
|
#include <QtSql/QSqlError>
|
|
#include <QtSql/QSqlRecord>
|
|
#include <QVariant>
|
|
#include <QDebug>
|
|
#include <QString>
|
|
#include <QList>
|
|
#include <QMap>
|
|
#include <qcoreapplication.h>
|
|
#include <qdir.h>
|
|
#include <qtimer.h>
|
|
#include <chrono>
|
|
#include <qobject.h>
|
|
#include <generalJsonParsing.hpp>
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <qelapsedtimer.h>
|
|
#include <QQueue>
|
|
#include <quuid.h>
|
|
#include <global.h>
|
|
#include <qthread.h>
|
|
#include <qmutex.h>
|
|
|
|
class SQLiteDB {
|
|
public:
|
|
QSqlDatabase db;
|
|
// 新增:全局互斥锁,保护所有数据库操作
|
|
mutable std::mutex db_mutex;
|
|
|
|
SQLiteDB(const QString& dbPath)
|
|
: dbPath(dbPath) {
|
|
connect();
|
|
}
|
|
~SQLiteDB() { disconnect(); };
|
|
|
|
// 所有公有方法加锁保护
|
|
bool execute(const QString& queryStr, const QVariantList& args = {}) {
|
|
std::lock_guard<std::mutex> lock(db_mutex);
|
|
QSqlQuery query(db);
|
|
query.prepare(queryStr);
|
|
|
|
for (int i = 0; i < args.size(); ++i) {
|
|
query.bindValue(i, args[i]);
|
|
}
|
|
|
|
if (!query.exec()) {
|
|
qCritical() << "SQL error:" << query.lastError().text();
|
|
qCritical() << "Query:" << queryStr;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
QList<QMap<QString, QVariant>> query(const QString& queryStr, const QVariantList& args = {}) {
|
|
std::lock_guard<std::mutex> lock(db_mutex);
|
|
QList<QMap<QString, QVariant>> results;
|
|
QSqlQuery query(db);
|
|
query.prepare(queryStr);
|
|
|
|
for (int i = 0; i < args.size(); ++i) {
|
|
query.bindValue(i, args[i]);
|
|
}
|
|
|
|
if (!query.exec()) {
|
|
qCritical() << "SQL error:" << query.lastError().text();
|
|
qCritical() << "Query:" << queryStr;
|
|
return results;
|
|
}
|
|
|
|
while (query.next()) {
|
|
QMap<QString, QVariant> row;
|
|
for (int i = 0; i < query.record().count(); ++i) {
|
|
row.insert(query.record().fieldName(i), query.value(i));
|
|
}
|
|
results.append(row);
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
bool createTable(const QString& tableName, const QList<std::pair<QString, QString>>& columns) {
|
|
std::lock_guard<std::mutex> lock(db_mutex);
|
|
if (columns.empty()) {
|
|
qDebug() << "Create table failed: columns are empty.";
|
|
return false;
|
|
}
|
|
|
|
QStringList columnDefinitions;
|
|
for (const auto& pair : columns) {
|
|
columnDefinitions << QString("%1 %2").arg(pair.first).arg(pair.second);
|
|
}
|
|
|
|
QString sql = QString("CREATE TABLE IF NOT EXISTS \"%1\" (%2)")
|
|
.arg(tableName)
|
|
.arg(columnDefinitions.join(", "));
|
|
QSqlQuery query(db);
|
|
bool res = query.exec(sql);
|
|
return res;
|
|
}
|
|
|
|
std::vector<QString> getTables() {
|
|
std::lock_guard<std::mutex> lock(db_mutex);
|
|
std::vector<QString> tables;
|
|
QString sql = "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%';";
|
|
QSqlQuery query(db);
|
|
if (!query.exec(sql)) {
|
|
qDebug() << "getTables failed:" << query.lastError().text();
|
|
return tables;
|
|
}
|
|
while (query.next()) {
|
|
tables.push_back(query.value(0).toString());
|
|
}
|
|
return tables;
|
|
}
|
|
|
|
bool dropTable(const QString& tableName) {
|
|
std::lock_guard<std::mutex> lock(db_mutex);
|
|
QString sql = QString("DROP TABLE IF EXISTS %1").arg(tableName);
|
|
return execute(sql);
|
|
}
|
|
|
|
bool addColumn(const QString& tableName, const QString& columnName, const QString& columnType) {
|
|
std::lock_guard<std::mutex> lock(db_mutex);
|
|
if (columnName.isEmpty() || columnType.isEmpty()) {
|
|
qDebug() << "Add column failed: column name or type is empty.";
|
|
return false;
|
|
}
|
|
|
|
QString sql = QString("ALTER TABLE \"%1\" ADD COLUMN \"%2\" %3").arg(tableName, columnName, columnType);
|
|
|
|
QSqlQuery query(db);
|
|
query.prepare(sql);
|
|
|
|
if (!query.exec()) {
|
|
qDebug() << "Add column failed:" << query.lastError().text();
|
|
return false;
|
|
}
|
|
|
|
qDebug() << "Column" << columnName << "added to table" << tableName;
|
|
return true;
|
|
}
|
|
|
|
bool tableExists(const QString& tableName) {
|
|
std::lock_guard<std::mutex> lock(db_mutex);
|
|
QString sql = QString("SELECT name FROM sqlite_master WHERE type='table' AND name='%1';").arg(tableName);
|
|
|
|
QList<QMap<QString, QVariant>> result = query(sql);
|
|
return !result.isEmpty();
|
|
}
|
|
|
|
bool _insert(const QString& tableName,
|
|
const std::map<QString, QVariant>& data) {
|
|
std::lock_guard<std::mutex> lock(db_mutex);
|
|
if (data.empty()) {
|
|
qDebug() << "Insert failed: data is empty.";
|
|
return false;
|
|
}
|
|
|
|
if (tableName.isEmpty()) {
|
|
qDebug() << "Insert failed: tableName is empty.";
|
|
return false;
|
|
}
|
|
|
|
QStringList columns, values;
|
|
for (const auto& pair : data) {
|
|
columns << pair.first;
|
|
values << "'" + pair.second.toString().replace("'", "''") + "'";
|
|
}
|
|
|
|
QString sql = QString("INSERT INTO \"%1\" (%2) VALUES (%3)")
|
|
.arg(tableName)
|
|
.arg(columns.join(", "))
|
|
.arg(values.join(", "));
|
|
|
|
qDebug() << "Generated SQL: " << sql;
|
|
|
|
QSqlQuery query(db);
|
|
|
|
if (!db.isOpen()) {
|
|
qDebug() << "Database is not open!";
|
|
return false;
|
|
}
|
|
|
|
if (!query.exec(sql)) {
|
|
qDebug() << "Insert failed:" << query.lastError().text();
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool _update(const QString& tableName,
|
|
const std::map<QString, QVariant>& data,
|
|
const std::map<QString, QVariant>& conditions) {
|
|
std::lock_guard<std::mutex> lock(db_mutex);
|
|
if (data.empty() || conditions.empty()) {
|
|
qDebug() << "Update failed: data or conditions are empty.";
|
|
return false;
|
|
}
|
|
|
|
QStringList setClauses;
|
|
for (const auto& pair : data) {
|
|
QString value = pair.second.toString().replace("'", "''");
|
|
setClauses << QString("%1 = '%2'").arg(pair.first).arg(value);
|
|
}
|
|
|
|
QStringList whereClauses;
|
|
for (const auto& pair : conditions) {
|
|
QString conditionValue = pair.second.toString().replace("'", "''");
|
|
whereClauses << QString("%1 = '%2'").arg(pair.first).arg(conditionValue);
|
|
}
|
|
|
|
QString sql = QString("UPDATE \"%1\" SET %2 WHERE %3")
|
|
.arg(tableName)
|
|
.arg(setClauses.join(", "))
|
|
.arg(whereClauses.join(" AND "));
|
|
|
|
qDebug() << "Generated SQL: " << sql;
|
|
|
|
QSqlQuery query(db);
|
|
|
|
if (!db.isOpen()) {
|
|
qDebug() << "Database is not open!";
|
|
return false;
|
|
}
|
|
|
|
if (!query.exec(sql)) {
|
|
qDebug() << "Update failed:" << query.lastError().text();
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool _delete(const QString& tableName,
|
|
const std::map<QString, QVariant>& conditions) {
|
|
std::lock_guard<std::mutex> lock(db_mutex);
|
|
if (conditions.empty()) {
|
|
qDebug() << "Delete failed: conditions are empty.";
|
|
return false;
|
|
}
|
|
|
|
QStringList whereClauses;
|
|
for (const auto& pair : conditions) {
|
|
whereClauses << QString("%1 = :%2").arg(pair.first).arg(pair.first + "_condition");
|
|
}
|
|
|
|
QString sql = QString("DELETE FROM \"%1\" WHERE %2")
|
|
.arg(tableName)
|
|
.arg(whereClauses.join(" AND "));
|
|
|
|
QSqlQuery query(db);
|
|
query.prepare(sql);
|
|
|
|
for (const auto& pair : conditions) {
|
|
query.bindValue(":" + pair.first + "_condition", QVariant::fromValue(pair.second));
|
|
}
|
|
|
|
if (!query.exec()) {
|
|
qDebug() << "Delete failed:" << query.lastError().text();
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
std::vector<std::map<QString, QVariant>> _search(const QString& tableName,
|
|
const QStringList& columns,
|
|
const std::map<QString, QVariant>& conditions = {}) {
|
|
std::lock_guard<std::mutex> lock(db_mutex);
|
|
QStringList selectColumns = columns.isEmpty() ? QStringList("*") : columns;
|
|
|
|
QString sql = QString("SELECT %1 FROM \"%2\"").arg(selectColumns.join(", "), tableName);
|
|
|
|
if (!conditions.empty()) {
|
|
QStringList whereClauses;
|
|
for (const auto& pair : conditions) {
|
|
QString value = pair.second.toString().replace("'", "''");
|
|
whereClauses << QString("%1 = '%2'").arg(pair.first).arg(value);
|
|
}
|
|
sql += " WHERE " + whereClauses.join(" AND ");
|
|
}
|
|
|
|
qDebug() << "Generated SQL: " << sql;
|
|
|
|
QSqlQuery query(db);
|
|
|
|
if (!db.isOpen()) {
|
|
qDebug() << "Database is not open!";
|
|
return {};
|
|
}
|
|
|
|
if (!query.exec(sql)) {
|
|
qDebug() << "Search failed:" << query.lastError().text();
|
|
return {};
|
|
}
|
|
|
|
std::vector<std::map<QString, QVariant>> results;
|
|
while (query.next()) {
|
|
std::map<QString, QVariant> row;
|
|
for (int i = 0; i < query.record().count(); ++i) {
|
|
row[query.record().fieldName(i)] = query.value(i);
|
|
}
|
|
results.push_back(row);
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
QList<QMap<QString, QVariant>> queryTabelData(const QString& tableName) {
|
|
std::lock_guard<std::mutex> lock(db_mutex);
|
|
QString sql = QString("SELECT * FROM \"%1\"").arg(tableName);
|
|
return query(sql);
|
|
}
|
|
|
|
bool exportTableToCSV(const QString& tableName, const QString& filePath, std::mutex& _mutex) {
|
|
std::lock_guard<std::mutex> lock(db_mutex);
|
|
using namespace std::chrono;
|
|
|
|
auto start = high_resolution_clock::now();
|
|
QString csvFileName = filePath;
|
|
QString sql = QString("SELECT * FROM \"%1\"").arg(tableName);
|
|
QSqlQuery query(db);
|
|
|
|
if (!query.exec(sql)) {
|
|
qCritical() << "Query execution failed: " << query.lastError().text();
|
|
return false;
|
|
}
|
|
|
|
if (!query.next()) {
|
|
qDebug() << "No data found in table" << tableName;
|
|
return false;
|
|
}
|
|
|
|
QFile file(csvFileName);
|
|
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
|
qCritical() << "Failed to open file" << csvFileName;
|
|
return false;
|
|
}
|
|
|
|
QTextStream out(&file);
|
|
|
|
QSqlRecord record = query.record();
|
|
QStringList columns;
|
|
for (int i = 0; i < record.count(); ++i) {
|
|
columns << record.fieldName(i);
|
|
}
|
|
|
|
out << columns.join(",") << "\n";
|
|
|
|
do {
|
|
QStringList values;
|
|
for (const auto& column : columns) {
|
|
values << query.value(column).toString();
|
|
}
|
|
out << values.join(",") << "\n";
|
|
} while (query.next());
|
|
|
|
file.close();
|
|
auto end = high_resolution_clock::now();
|
|
auto duration = duration_cast<milliseconds>(end - start);
|
|
qDebug() << csvFileName << "EXPORT CSV COST: " << duration.count() << "ms";
|
|
return true;
|
|
}
|
|
|
|
bool setWALMode(bool enableWAL = true, int busyTimeoutMs = 3000) {
|
|
std::lock_guard<std::mutex> lock(db_mutex);
|
|
if (!db.isOpen()) {
|
|
qWarning() << "Database is not open, cannot set WAL mode.";
|
|
return false;
|
|
}
|
|
|
|
QSqlQuery pragma(db);
|
|
|
|
QString mode = enableWAL ? "WAL" : "DELETE";
|
|
if (!pragma.exec(QString("PRAGMA journal_mode=%1;").arg(mode))) {
|
|
qWarning() << "Failed to set journal_mode:" << pragma.lastError().text();
|
|
return false;
|
|
}
|
|
qDebug() << "SQLite journal_mode set to" << mode;
|
|
|
|
if (enableWAL) {
|
|
pragma.exec("PRAGMA synchronous=NORMAL;");
|
|
}
|
|
|
|
pragma.exec(QString("PRAGMA busy_timeout=%1;").arg(busyTimeoutMs));
|
|
|
|
return true;
|
|
}
|
|
|
|
private:
|
|
bool connect() {
|
|
m_connectionName = QUuid::createUuid().toString();
|
|
|
|
if (!QFile::exists(dbPath)) {
|
|
QFileInfo fi(dbPath);
|
|
QDir().mkpath(fi.absolutePath());
|
|
qDebug() << "Database file does not exist. Creating a new database:" << dbPath;
|
|
}
|
|
|
|
db = QSqlDatabase::addDatabase("QSQLITE", m_connectionName);
|
|
db.setDatabaseName(dbPath);
|
|
|
|
if (!db.open()) {
|
|
qCritical() << "Failed to open or create database:" << db.lastError().text();
|
|
return false;
|
|
}
|
|
|
|
qDebug() << "Connected to SQLite database:" << dbPath;
|
|
|
|
{
|
|
QSqlQuery pragma(db);
|
|
|
|
if (!pragma.exec("PRAGMA journal_mode=WAL;")) {
|
|
qWarning() << "Failed to enable WAL mode:" << pragma.lastError().text();
|
|
}
|
|
else {
|
|
qDebug() << "SQLite WAL mode enabled.";
|
|
}
|
|
pragma.exec("PRAGMA synchronous=NORMAL;");
|
|
pragma.exec("PRAGMA busy_timeout=3000;");
|
|
}
|
|
|
|
createTable("setting",
|
|
{
|
|
{"id","INTEGER PRIMARY KEY AUTOINCREMENT"} ,
|
|
});
|
|
|
|
return true;
|
|
}
|
|
|
|
void disconnect() {
|
|
QSqlDatabase::removeDatabase(m_connectionName);
|
|
if (db.isOpen()) {
|
|
db.close();
|
|
qDebug() << "Database closed.";
|
|
}
|
|
}
|
|
|
|
QString m_connectionName;
|
|
QString dbPath;
|
|
};
|
|
|
|
class CsvWriter : public QThread{
|
|
public:
|
|
CsvWriter(SQLiteDB* dbIn):db(dbIn){
|
|
try{
|
|
m_json = readJsonFromPath("./sqldrivers/sqliteCfg.json");
|
|
for (auto& data : m_json["数据列表"]) {
|
|
db_InitColumns.append({ QString::fromStdString(data),"TEXT" });
|
|
}
|
|
for (auto& data : m_json["链接到UI表格数据列表"].items()) {
|
|
csvAndChartLink[QString::fromStdString(data.key())] = QString::fromStdString(data.value());
|
|
}
|
|
if (m_json["新增数据列表"].size() > 0) {
|
|
for (auto& data : m_json["新增数据列表"]) {
|
|
db_newCol.append({ QString::fromStdString(data),"TEXT" });
|
|
}
|
|
m_json["新增数据列表"].clear();
|
|
saveJsonFromPath("./sqldrivers/sqliteCfg.json", m_json);
|
|
}
|
|
for (auto& data : m_json["判断NG依据数据列表"]) {
|
|
isNgDepends.push_back(QString::fromStdString(data));
|
|
}
|
|
}
|
|
catch (const std::exception&){
|
|
std::cerr << "readJsonFromPath error" << std::endl;
|
|
}
|
|
init();
|
|
}
|
|
~CsvWriter(){
|
|
//stopAutoExport();
|
|
}
|
|
std::map<QString, QString>csvAndChartLink;
|
|
|
|
SQLiteDB* db;
|
|
|
|
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;
|
|
}
|
|
QMutexLocker locker(&queueLock);
|
|
queue.enqueue(std::make_pair(snCode, data));
|
|
this->start();
|
|
}
|
|
|
|
bool isNewData(const QString& snCode) {
|
|
std::lock_guard<std::mutex> locker(db->db_mutex);
|
|
auto res = db->_search(getCurrentProcessCsvName(), {}, { {"条码",snCode} });
|
|
return res.empty();
|
|
}
|
|
bool isNgData(const QString& snCode) {
|
|
std::lock_guard<std::mutex> locker(db->db_mutex);
|
|
auto res = db->_search(getCurrentProcessCsvName(), {}, { {"条码",snCode} });
|
|
if (res.empty() == true)
|
|
return false;
|
|
for (auto& data : isNgDepends) {
|
|
if (res[0][data].toString() == "NG")
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void run() override{
|
|
while (queue.size() > 0) {
|
|
queueLock.lock();
|
|
auto val = queue.dequeue();
|
|
queueLock.unlock();
|
|
try {
|
|
auto snCode = val.first;
|
|
auto data = val.second;
|
|
QString currentProcessCsvName = getCurrentProcessCsvName();
|
|
if (currentProcessCsvName != currentProcessCsvNameCache) {
|
|
std::lock_guard<std::mutex> locker(db->db_mutex);
|
|
if (!db->createTable(currentProcessCsvName, db_InitColumns)) {
|
|
qWarning() << "addtData: Failed to create table:" << currentProcessCsvName;
|
|
return;
|
|
}
|
|
currentProcessCsvNameCache = currentProcessCsvName;
|
|
}
|
|
QList<QString> tableColumns;
|
|
{
|
|
std::lock_guard<std::mutex> locker(db->db_mutex);
|
|
QSqlQuery colQuery(db->db);
|
|
QString colSql = QString("PRAGMA table_info(\"%1\")").arg(currentProcessCsvName);
|
|
if (colQuery.exec(colSql)) {
|
|
while (colQuery.next()) {
|
|
tableColumns.append(colQuery.value(1).toString());
|
|
}
|
|
}
|
|
}
|
|
for (const auto& kv : data) {
|
|
std::lock_guard<std::mutex> locker(db->db_mutex);
|
|
if (!tableColumns.contains(kv.first)) {
|
|
if (!db->addColumn(currentProcessCsvName, kv.first, "TEXT")) {
|
|
qWarning() << "addtData: Failed to add column:" << kv.first << "to table:" << currentProcessCsvName;
|
|
}
|
|
}
|
|
}
|
|
std::vector<std::map<QString, QVariant>> res;
|
|
{
|
|
std::lock_guard<std::mutex> locker(db->db_mutex);
|
|
res = db->_search(currentProcessCsvName, {}, { {"条码",snCode} });
|
|
}
|
|
QString nowTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz");
|
|
bool opResult = false;
|
|
if (res.empty()) {
|
|
std::vector<std::map<QString, QVariant>> lastRes;
|
|
{
|
|
std::lock_guard<std::mutex> locker(db->db_mutex);
|
|
lastRes = db->_search(getLastProcessCsvName(), {}, { {"条码",snCode} });
|
|
}
|
|
if (lastRes.empty()) {
|
|
std::map<QString, QVariant> insertData = data;
|
|
insertData["条码"] = snCode;
|
|
insertData["创建时间"] = nowTime;
|
|
insertData["修改时间"] = nowTime;
|
|
std::lock_guard<std::mutex> locker(db->db_mutex);
|
|
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;
|
|
std::lock_guard<std::mutex> locker(db->db_mutex);
|
|
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;
|
|
std::lock_guard<std::mutex> locker(db->db_mutex);
|
|
opResult = db->_update(getCurrentProcessCsvName(), updateData, { {"条码",snCode} });
|
|
if (!opResult) {
|
|
qWarning() << "addtData: Update failed for table:" << getCurrentProcessCsvName() << "snCode:" << snCode;
|
|
}
|
|
}
|
|
}
|
|
catch (const std::exception& ex) {
|
|
qCritical() << "addtData: Exception caught:" << ex.what();
|
|
}
|
|
catch (...) {
|
|
qCritical() << "addtData: Unknown exception caught.";
|
|
}
|
|
}
|
|
}
|
|
|
|
private:
|
|
QMutex queueLock;
|
|
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;
|
|
int m_intervalMs = 10000;
|
|
QElapsedTimer timer;
|
|
QString currentProcessCsvNameCache;
|
|
nlohmann::json m_json;
|
|
QList<std::pair<QString, QString>> db_newCol = {};
|
|
QList<std::pair<QString, QString>> db_InitColumns = {
|
|
{"条码", "TEXT NOT NULL PRIMARY KEY"},
|
|
{"创建时间", "TEXT"},
|
|
{"修改时间", "TEXT"},
|
|
{"CT", "TEXT"},
|
|
};
|
|
|
|
void init(){
|
|
std::lock_guard<std::mutex> locker(_mutex);
|
|
if (!db->createTable(getLastProcessCsvName(), db_InitColumns)) {
|
|
qDebug() << "Failed to create table " << getLastProcessCsvName();
|
|
}
|
|
currentProcessCsvNameCache = getCurrentProcessCsvName();
|
|
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);
|
|
}
|
|
timer.start();
|
|
}
|
|
|
|
QString getCurrentProcessCsvName() {
|
|
QDateTime currentDateTime = QDateTime::currentDateTime();
|
|
int hour = currentDateTime.time().hour();
|
|
int minute = currentDateTime.time().minute();
|
|
bool isDayShift = (hour > 8 || (hour == 8 && minute >= 30)) && (hour < 20 || (hour == 20 && minute <= 30));
|
|
bool isDayBefore = hour <= 8 || (hour == 8 && minute <= 29);
|
|
QString dateStr;
|
|
if (isDayBefore == true)
|
|
dateStr = currentDateTime.addDays(-1).toString("yyyy-MM-dd");
|
|
else
|
|
dateStr = currentDateTime.toString("yyyy-MM-dd");
|
|
if (isDayShift) {
|
|
return (dateStr + "白班");
|
|
}
|
|
else {
|
|
return (dateStr + "夜班");
|
|
}
|
|
}
|
|
|
|
QString getLastProcessCsvName() {
|
|
QDateTime currentDateTime = QDateTime::currentDateTime();
|
|
int hour = currentDateTime.time().hour();
|
|
int minute = currentDateTime.time().minute();
|
|
bool isDayShift = (hour == 8 && minute >= 30) && (hour == 20 && minute <= 30);
|
|
bool isDayBefore = hour == 20 && minute <= 30;
|
|
QDateTime lastShiftDateTime;
|
|
if (isDayBefore) {
|
|
lastShiftDateTime = currentDateTime.addDays(-1);
|
|
}
|
|
else
|
|
lastShiftDateTime = currentDateTime;
|
|
QString dateStr = lastShiftDateTime.toString("yyyy-MM-dd");
|
|
if (isDayShift) {
|
|
return (dateStr + "夜班");
|
|
}
|
|
else {
|
|
return (dateStr + "白班");
|
|
}
|
|
}
|
|
|
|
void exportCsv(){
|
|
QString name = getLastProcessCsvName();
|
|
db->exportTableToCSV(name, "./csv/"+ name +".csv", _mutex);
|
|
name = getCurrentProcessCsvName();
|
|
db->exportTableToCSV(name, "./csv/" + name + ".csv", _mutex);
|
|
QString currentProcessCsvName = getCurrentProcessCsvName();
|
|
if (currentProcessCsvName != currentProcessCsvNameCache)
|
|
if (!db->createTable(currentProcessCsvName, db_InitColumns)) {
|
|
return;
|
|
}
|
|
else
|
|
currentProcessCsvNameCache = currentProcessCsvName;
|
|
}
|
|
};
|
|
|
|
#pragma once |