From 26601406268875b3c13bf44be89760988500f98d Mon Sep 17 00:00:00 2001 From: baiYue Date: Fri, 21 Mar 2025 12:53:45 +0800 Subject: [PATCH] generate project model completed --- CMakeLists.txt | 5 +- common/include/global.h | 129 +- diagramCavas/CMakeLists.txt | 4 +- diagramUtils/CMakeLists.txt | 50 + {common => diagramUtils}/include/dataBase.h | 157 +-- diagramUtils/include/logger.h | 69 + {common => diagramUtils}/source/dataBase.cpp | 1236 ++++++++++-------- diagramUtils/source/logger.cpp | 155 +++ include/electricElementsBox.h | 1 + source/electricElementsBox.cpp | 7 +- source/projectModelDlg.cpp | 91 +- 11 files changed, 1170 insertions(+), 734 deletions(-) create mode 100644 diagramUtils/CMakeLists.txt rename {common => diagramUtils}/include/dataBase.h (59%) create mode 100644 diagramUtils/include/logger.h rename {common => diagramUtils}/source/dataBase.cpp (56%) create mode 100644 diagramUtils/source/logger.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a67d1cf..75a0a6d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,7 +49,6 @@ set(H_HEADER_FILES include/renameModel.h common/include/global.h - common/include/dataBase.h common/include/httpInterface.h common/include/compiler.hpp common/include/export.hpp @@ -70,7 +69,6 @@ set(CPP_SOURCE_FILES source/projectModelDlg.cpp source/renameModel.cpp - common/source/dataBase.cpp common/source/httpInterface.cpp ) set(UI_FILES @@ -136,7 +134,8 @@ set_target_properties(DiagramDesigner PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${dd_PlatformDir}/bin" ) -target_link_libraries(DiagramDesigner PRIVATE diagramCavas) +target_link_libraries(DiagramDesigner PRIVATE diagramCavas diagramUtils) add_subdirectory(diagramCavas) +add_subdirectory(diagramUtils) file(COPY setting.xml DESTINATION "${CMAKE_BINARY_DIR}/${dd_PlatformDir}/bin") diff --git a/common/include/global.h b/common/include/global.h index 73f672e..c269eb4 100644 --- a/common/include/global.h +++ b/common/include/global.h @@ -5,6 +5,8 @@ #include #include #include +#include +#include const double g_dGriaphicsScene_Width = 800; const double g_dGriaphicsScene_Height = 600; @@ -25,6 +27,11 @@ enum GraphicsItemType GIT_link= QGraphicsItem::UserType + 53 }; +enum AbstractItemType //工程模关联的对象类型 +{ + +}; + enum DiagramMode //组态图模式 { DM_edit = 0, @@ -35,14 +42,120 @@ enum Attribute //元模属性字段对照 { Id = Qt::UserRole + 1, Attribute = Qt::UserRole + 2, - DataType = Qt::UserRole + 3, - LengthPrecision = Qt::UserRole + 4, - Scale = Qt::UserRole + 5, - DefaultValue = Qt::UserRole + 6, - ValueRange = Qt::UserRole + 7, - AttributeGroup = Qt::UserRole + 8, - IsNotNull = Qt::UserRole + 9, - IsIndex = Qt::UserRole + 10 + AttributeName = Qt::UserRole + 3, + DataType = Qt::UserRole + 4, + LengthPrecision = Qt::UserRole + 5, + Scale = Qt::UserRole + 6, + IsNotNull = Qt::UserRole + 7, + DefaultValue = Qt::UserRole + 8, + ValueRange = Qt::UserRole + 9, +}; + +struct attributeGroup //属性组(元模) +{ + int id = 0; + QString groupType; + QString groupName; + int isPublic = -1; + QString remark; +}; + +struct dataType //数据类型(元模) +{ + int id = 0; + QString dataType; + QString databaseType; +}; + +struct modelType //模型类型 +{ + int id = 0; + QString modelType; + QString modelName; + QString remark; +}; + +struct modelGroup +{ + int id = 0; + qint64 modelTypeId = 0; + qint64 attributeGroupId = 0; +}; + +struct attribute //属性表(元模属性字段) +{ + int id = 0; + QString attribute; //属性名 + QString attributeName; //别名(中文名) + qint64 dataTypeId = 0; //数据类型id + int lengthPrecision=0; //长度限制(varchar) + int scale=0; //小数点位数 + int isNotNull=0; //是否非空 + QString defaultValue; //默认值 + QString valueRange; //数值范围 +}; + +struct modelAttribute //模型属性表(所有模型属性的索引) +{ + int id = 0; + qint64 modelTypeId = 0; + qint64 attributeGroupId = 0; + qint64 attributeId = 0; +}; + +struct modelConnectivity //模型连接性表(元模是否可以连接) +{ + int id = 0; + QString fromModel; //属性名 + QString toModel; + int connectivity=0; //是否可连 +}; + +//===================================== +struct projectManager //工程模管理类 +{ + int id = 0; + QString name; //工程模表名 + QString tag; //工程模名称 + QString metaModel; //元模名 + QString groupName; //属性组名 + int linkType; //图元链接类型 + QJsonObject checkState; //属性选择状态 +}; + +//================================================== + +struct componentInfo +{ + int id = 0; + QUuid uuid; + QString nspath; + QString tag; + QString name; + QString description; + QString grid; + QString zone; + QString station; + int type = 0; + bool inService = true; + int state = 0; + QJsonObject connected_bus; + QJsonObject label; + QJsonObject context; + int page_id = 0; + int op = 0; +}; + +struct busStability +{ + int componentId = 0; + double resistance = 0; + bool anchor_v = false; + double uv_alarm = 0; + double ov_alarm = 0; + bool anchor_i = false; + double ui_alarm = 0; + double oi_alarm = 0; }; //Q_ENUM_NS(GraphicsItemType) diff --git a/diagramCavas/CMakeLists.txt b/diagramCavas/CMakeLists.txt index f6210a8..7a2f799 100644 --- a/diagramCavas/CMakeLists.txt +++ b/diagramCavas/CMakeLists.txt @@ -34,7 +34,6 @@ set(DIAGRAMCAVAS_HEADER_FILES include/util/scalingSelector.h include/util/selectorManager.h include/util/subMovingSelector.h - ../common/include/dataBase.h ../common/include/httpInterface.h ../common/include/global.h ../common/include/compiler.hpp @@ -76,7 +75,6 @@ set(DIAGRAMCAVAS_SOURCE_FILES source/util/scalingSelector.cpp source/util/selectorManager.cpp source/util/subMovingSelector.cpp - ../common/source/dataBase.cpp ../common/source/httpInterface.cpp ) @@ -116,6 +114,8 @@ option(BUILD_SHARED_LIBS "Build as shared library" ON) target_include_directories(diagramCavas PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_link_libraries(diagramCavas PRIVATE diagramUtils) + target_compile_definitions(diagramCavas PUBLIC DIAGRAM_DESIGNER_SHARED diff --git a/diagramUtils/CMakeLists.txt b/diagramUtils/CMakeLists.txt new file mode 100644 index 0000000..c1106a4 --- /dev/null +++ b/diagramUtils/CMakeLists.txt @@ -0,0 +1,50 @@ +project(diagramUtils) + +set(DIAGRAMUTILS_HEADER_FILES + include/logger.h + ../common/include/global.h + ../common/include/compiler.hpp + ../common/include/export.hpp + ../common/include/operatingSystem.hpp +) + +set(DIAGRAMUTILS_SOURCE_FILES + source/logger.cpp + source/dataBase.cpp +) + + +if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) + qt_add_library(diagramUtils SHARED + MANUAL_FINALIZATION + ${DIAGRAMUTILS_HEADER_FILES} + ${DIAGRAMUTILS_SOURCE_FILES} + ) +else() + add_library(diagramUtils SHARED + ${DIAGRAMUTILS_HEADER_FILES} + ${DIAGRAMUTILS_SOURCE_FILES} + ) +endif() + +target_link_libraries(diagramUtils PUBLIC Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::Gui + Qt${QT_VERSION_MAJOR}::Widgets) + +target_link_libraries(diagramUtils PRIVATE Qt6::Xml) +target_link_libraries(diagramUtils PRIVATE Qt6::Network) +target_link_libraries(diagramUtils PRIVATE Qt6::Sql ${POSTGRESQL_LIBRARIES}) + +option(BUILD_SHARED_LIBS "Build as shared library" ON) + + + +target_include_directories(diagramUtils PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) + +target_compile_definitions(diagramUtils + PUBLIC + DIAGRAM_DESIGNER_SHARED + PRIVATE + DIAGRAM_DESIGNER_EXPORTS + #QT_NO_KEYWORDS +) diff --git a/common/include/dataBase.h b/diagramUtils/include/dataBase.h similarity index 59% rename from common/include/dataBase.h rename to diagramUtils/include/dataBase.h index f146922..8db58c2 100644 --- a/common/include/dataBase.h +++ b/diagramUtils/include/dataBase.h @@ -5,142 +5,27 @@ #include #include #include +#include "global.h" +#include "export.hpp" -struct attributeGroup //属性组(元模) -{ - int id = 0; - QString group; - QString groupName; -}; -struct dataType //数据类型(元模) -{ - int id = 0; - QString dataType; - QString databaseType; -}; - -struct attribute //属性表(元模属性字段) -{ - int id = 0; - QString attribute; //属性名 - int dataType; //数据类型 - int lengthPrecision=0; //长度限制(varchar) - int scale=0; //小数点位数 - QString defaultValue; //默认值 - QString valueRange; //数值范围 - int attributeGroup=0; //属性组 - int isNotNull=0; //是否非空 - int isIndex=0; //是否index -}; - -struct modelAttribute //模型-属性对应表(元模在此表查找) -{ - int id = 0; - QString modelType; //元模名 - int attributeId; //属性id -}; - -struct modelConnectivity //模型连接性表(元模是否可以连接) -{ - int id = 0; - QString fromModel; //属性名 - QString toModel; - int connectivity=0; //是否可连 -}; - -//================================================== -struct availableID //可用id -{ - int componentId = -1; - int pageId = -1; - int stationId = -1; - int gridId = -1; - int zoneId = -1; - int topoId = -1; -}; - -struct componentInfo -{ - int id = 0; - QUuid uuid; - QString nspath; - QString tag; - QString name; - QString description; - QString grid; - QString zone; - QString station; - int type = 0; - bool inService = true; - int state = 0; - QJsonObject connected_bus; - QJsonObject label; - QJsonObject context; - int page_id = 0; - int op = 0; - componentInfo& operator=(const componentInfo& obj) - { - if(this == &obj) - return *this; - id = obj.id; - uuid = obj.uuid; - nspath = obj.nspath; - tag = obj.tag; - name = obj.name; - description = obj.description; - grid = obj.grid; - zone = obj.zone; - station = obj.station; - type = obj.type; - inService = obj.inService; - state = obj.state; - connected_bus = obj.connected_bus; - label = obj.label; - context = obj.context; - page_id = obj.page_id; - op = obj.op; - return *this; - } -}; - -struct busStability -{ - int componentId = 0; - double resistance = 0; - bool anchor_v = false; - double uv_alarm = 0; - double ov_alarm = 0; - bool anchor_i = false; - double ui_alarm = 0; - double oi_alarm = 0; - busStability& operator=(const busStability& obj) - { - if(this == &obj) - return *this; - componentId = obj.componentId; - resistance = obj.resistance; - anchor_v = obj.anchor_v; - uv_alarm = obj.uv_alarm; - ov_alarm = obj.ov_alarm; - anchor_i = obj.anchor_i; - ui_alarm = obj.ui_alarm; - oi_alarm = obj.oi_alarm; - return *this; - } -}; - -class DataBase +class DIAGRAM_DESIGNER_PUBLIC DataBase { //Q_OBJECT public: DataBase(); ~DataBase(); + QSqlQuery executeSQL(const QString& strSQL, bool createOrDrop = false,const QVariantList& params = {}, bool useTranscation = false); + /** + * @brief 多条批量SQL语句执行接口 + * @param sqlStatements SQL语句列表 + * @param paramsList 参数列表(要与SQL语句一一对应) + */ + QSqlQuery executeBatchSQL(const QStringList& sqlStatements, bool createOrDrop = false, + const QList& paramsList = QList(), bool useTranscation = false); static DataBase* GetInstance(); + public: - availableID structID; -public: - void updateId(); bool insertPage(QString tag,QString name,int status,QJsonObject label,QJsonObject context,QString description,int op); bool insertStation(int zoneId,QString name,QString description,bool isLocal,int op); bool insertGrid(QString name,QString description,int op); @@ -173,14 +58,18 @@ public: //***********元模 bool getAttributeGroup(); //获取属性组信息 bool getDataType(); //获取数据类型信息 + bool getModelType(); //获取模型类型 + bool getModelGroup(); //获取模型组 bool getAttribute(); //获取属性 - bool getModelAttribute(); //获取元模 + bool getModelAttribute(); //获取模型-属性对照组 bool getModelConnectivity(); //获取连接性 QMap AttributeGroup() const {return _attributeGroup;} QMap DataType() const {return _dataType;} + QMap ModelType() const {return _modelType;} + QMap ModelGroup() const {return _modelGroup;} QMap Attribute() const {return _attribute;} - QMap ModelAttribute() const {return _modelAttribute;} + QMap ModelAttribute() const {return _modelAttribute;} QMap ModelConnectivity() const {return _modelConnectivity;} //***********工程模 bool createProjectManager(); //生成记录表,包含工程模名称,属性组名,启用和关闭的属性字段(json类型)[一个属性组建一个表] @@ -194,18 +83,23 @@ public: bool deleteTable(const QString&); //删除表 bool deleteRecordFromManager(const QString& sProject,const QString& sGroup); //删除某个模型下的组 bool modifyProjectTable(QString sTable,QMap mOld,QMap mNew); + //**********使用工程模 + QMap getAllProjectModel(); //获取所有工程模<名称,图元类型> + QMap getProjectModelGroupInfo(const QString&); //获取指定工程模所有属性组信息<属性组名,属性信息> private: QMap _attributeGroup; //属性组的组 QMap _dataType; //数据类型组 + QMap _modelType; //模型类型 + QMap _modelGroup; //模型组 QMap _attribute; //属性组 - QMap _modelAttribute; //元模组 + QMap _modelAttribute; //模型-属性对照组 QMap _modelConnectivity; //连接性组 private: void initial(); //bool createProjectDB(); //void initialProjectDB(); void readXML(); - static DataBase* instance; + static DataBase* dbInstance; static int _id; QSqlDatabase db; //QSqlDatabase prodb; @@ -217,6 +111,5 @@ private: int _Port; QString _UserName; QString _PassWord; - }; #endif // DATABASE_H diff --git a/diagramUtils/include/logger.h b/diagramUtils/include/logger.h new file mode 100644 index 0000000..a9dd5f6 --- /dev/null +++ b/diagramUtils/include/logger.h @@ -0,0 +1,69 @@ +#ifndef LOGGER_H +#define LOGGER_H + +#include +#include +#include + +// 日志宏定义 +#define LOG(level, module, message) Logger::instance().log(Logger::level, module, message) +#define LOG_DEBUG(module, message) LOG(DEBUG, module, message) +#define LOG_INFO(module, message) LOG(INFO, module, message) +#define LOG_WARN(module, message) LOG(WARNING, module, message) +#define LOG_ERROR(module, message) LOG(ERROR, module, message) +#define LOG_FATAL(module, message) LOG(FATAL, module, message) + +class Logger : public QObject +{ + Q_OBJECT + +public: + enum LogLevel + { + FATAL = 0, + ERROR, + WARNING, + INFO, + DEBUG + }; + + //获取单例实例 + static Logger& instance(); + void log(LogLevel, const QString&, const QString&); + +private: + explicit Logger(); + ~Logger(); + //禁止拷贝 + Logger(const Logger&) = delete; //delete关键字表示该函数不可用,包括编译器自动生成的函数 + Logger& operator=(const Logger&) = delete; + + void initialize(); + void loadConfig(/*const QString&*/); //本系统是通过Settings类进行配置文件信息读取 + void setLogFile(const QString&); + void shutdown(); + + void writeToFile(const QString&); + void rollLogFiles(); //当文件大小超过设置上线时会触发'滚动' + QString formatLogMessage(LogLevel, const QString&, const QString&); + + struct LogEntry + { + QDateTime time; + LogLevel level; + QString module; + QString message; + Qt::HANDLE threadId; + }; + + //配置参数 + LogLevel m_logLevel; + QString m_logFilePath; + QFile m_logFile; + qint64 m_maxFileSize; + int m_maxBackupFiles; + bool m_outputToConsole; + bool m_outputOtFile; +}; + +#endif //LOGGER_H diff --git a/common/source/dataBase.cpp b/diagramUtils/source/dataBase.cpp similarity index 56% rename from common/source/dataBase.cpp rename to diagramUtils/source/dataBase.cpp index 5fa4538..8e3ff78 100644 --- a/common/source/dataBase.cpp +++ b/diagramUtils/source/dataBase.cpp @@ -1,4 +1,5 @@ #include "dataBase.h" +#include "logger.h" #include #include #include @@ -9,7 +10,7 @@ #include #include -DataBase* DataBase::instance = nullptr; +DataBase* DataBase::dbInstance = nullptr; int DataBase::_id = 0; DataBase::DataBase() @@ -45,140 +46,185 @@ void DataBase::initial() if (db.open()) { qDebug()<<"baseDB success"; } else { - qDebug()<<"baseDB failed"; + LOG_ERROR("DB", QString("Database not open")); } //元模 - getAttributeGroup(); - getDataType(); - getAttribute(); + + getAttributeGroup(); //获取属性组信息 + getDataType(); //获取数据类型信息 + getModelType(); //获取模型类型 + getModelGroup(); //获取模型组 + getAttribute(); //获取属性 getModelAttribute(); - getModelConnectivity(); + getModelConnectivity(); //获取连接性 } -/*bool DataBase::createProjectDB() +DataBase* DataBase::GetInstance() { - QSqlQuery query(db); - QString sql = QString("CREATE DATABASE %1").arg(_ProjectDB); - if (!query.exec(sql)) { - qDebug() << "创建数据库失败:" << query.lastError().text(); - return false; - } - return true; -} - -void DataBase::initialProjectDB() -{ - if (QSqlDatabase::contains(_ProjectDB)) - prodb = QSqlDatabase::database(_ProjectDB); - else - prodb = QSqlDatabase::addDatabase(_DataBaseType,_ProjectDB); - - prodb.setDatabaseName(_ProjectDB); - prodb.setHostName(_HostName); - prodb.setPort(_Port); - // 需要改成自己的用户名和密码 - prodb.setUserName(_UserName); - prodb.setPassword(_PassWord); - - if (prodb.open()) { - qDebug()<<"ProjectDB success"; - } else { - //qDebug()<<"ProjectDB failed"; - qDebug()< id ? structID.componentId:id; - } - } - qry.finish(); - - success = qry.exec("SELECT id FROM station"); - if (!success) { - qDebug()< id ? structID.stationId:id; - } - } - qry.finish(); - - success = qry.exec("SELECT id FROM page"); - if (!success) { - qDebug()< id ? structID.pageId:id; - } - } - qry.finish(); - - success = qry.exec("SELECT id FROM grid"); - if (!success) { - qDebug()< id ? structID.gridId:id; - } - } - qry.finish(); - - success = qry.exec("SELECT id FROM zone"); - if (!success) { - qDebug()< id ? structID.zoneId:id; - } - } - qry.finish(); - - success = qry.exec("SELECT id FROM topologic"); - if (!success) { - qDebug()< id ? structID.topoId:id; - } - } - qry.clear(); + dbInstance = new DataBase(); } + return dbInstance; } +QSqlQuery DataBase::executeSQL(const QString& strSQL,bool createOrDrop,const QVariantList& params, bool useTranscation) +{ + //事务 + bool transactionStarted = false; + if(useTranscation) + { + if(!db.transaction()) + { + LOG_ERROR("DB", QString("Start transaction failed. error: %1").arg(db.lastError().databaseText())); + throw std::runtime_error(db.lastError().text().toStdString()); + } + transactionStarted = true; + } + + QSqlQuery sqlQuery(db); + try + { + if(createOrDrop) //创建或删除直接执行sql + { + if (!sqlQuery.exec(strSQL)) + { + LOG_ERROR("SQL", QString("SQL '%1' execute error: %2").arg(strSQL, sqlQuery.lastError().databaseText())); + throw std::runtime_error(db.lastError().text().toStdString()); + } + } + else + { + if(!sqlQuery.prepare(strSQL)) + { + LOG_ERROR("SQL", QString("SQL '%1' prepare fialed. error: %2").arg(strSQL, sqlQuery.lastError().databaseText())); + throw std::runtime_error(db.lastError().text().toStdString()); + } + //绑定参数 + + for(int i = 0;i < params.size();++i) + { + sqlQuery.bindValue(i, params[i]); + } + + if (!sqlQuery.exec()) + { + LOG_ERROR("SQL", QString("SQL '%1' execute error: %2").arg(strSQL, sqlQuery.lastError().databaseText())); + throw std::runtime_error(db.lastError().text().toStdString()); + } + } + + // 提交事务(如果已开启) + if(transactionStarted && !db.commit()) + { + throw std::runtime_error(db.lastError().text().toStdString()); + LOG_ERROR("DB", QString("Commit transaction failed. connectionName: %1").arg(db.lastError().databaseText())); + } + } + catch (const std::runtime_error& e) + { + // 错误处理:回滚事务(如果已开启) + if(transactionStarted) + { + if(!db.rollback()) // 回滚失败时记录警告 + { + LOG_ERROR("DB", QString("Rollback failed. connectionName: %1").arg(db.lastError().databaseText())); + } + } + + throw; // 重新抛出异常 + } + + return sqlQuery; +} + +//多条批量SQL语句执行接口 +QSqlQuery DataBase::executeBatchSQL(const QStringList& sqlStatements, bool createOrDrop,const QList& paramsList, bool useTranscation) +{ + + //参数数量校验 + if(!paramsList.isEmpty() && sqlStatements.size() != paramsList.size()) + { + LOG_ERROR("SQL", QString("SQL statement does not match the number of parameters")); + throw std::runtime_error(QSqlError("SQL statement does not match the number of parameters").text().toStdString()); + } + + //事务 + bool transactionStarted = false; + if(useTranscation) + { + if(!db.transaction()) + { + LOG_ERROR("DB", QString("Start transaction failed.")); + throw std::runtime_error(db.lastError().text().toStdString()); + } + transactionStarted = true; + } + + QSqlQuery lastQuery(db); + try + { + for(int i = 0; i < sqlStatements.size(); i++) + { + const QString& strSQL = sqlStatements.at(i); + const QVariantList& params = paramsList.isEmpty() ? QVariantList() : paramsList.at(i); + + QSqlQuery sqlQuery(db); + if(createOrDrop) + { + if (!sqlQuery.exec(strSQL)) + { + LOG_ERROR("SQL", QString("SQL '%1' execute error: %2").arg(strSQL, sqlQuery.lastError().databaseText())); + throw std::runtime_error(db.lastError().text().toStdString()); + } + } + else + { + if(!sqlQuery.prepare(strSQL)) + { + LOG_ERROR("SQL", QString("SQL '%1' prepare fialed. error: %2").arg(strSQL, sqlQuery.lastError().databaseText())); + throw std::runtime_error(db.lastError().text().toStdString()); + } + //绑定参数 + for(int i = 0;i < params.size();++i) + { + sqlQuery.bindValue(i, params[i]); + } + + if (!sqlQuery.exec()) + { + LOG_ERROR("SQL", QString("SQL '%1' execute error: %2").arg(strSQL, sqlQuery.lastError().databaseText())); + throw std::runtime_error(db.lastError().text().toStdString()); + } + } + + lastQuery = std::move(sqlQuery); + // 提交事务(如果已开启) + if(transactionStarted && !db.commit()) + { + throw std::runtime_error(db.lastError().text().toStdString()); + LOG_ERROR("DB", QString("Commit transaction failed.")); + } + } + } + catch (const std::runtime_error& e) + { + // 错误处理:回滚事务(如果已开启) + if(transactionStarted) + { + if(!db.rollback()) // 回滚失败时记录警告 + { + LOG_ERROR("DB", QString("Rollback failed. error: %1").arg( db.lastError().databaseText())); + } + } + + throw; // 重新抛出异常 + } + + return lastQuery; +} + + bool DataBase::insertComponent(QUuid uuid,QString nspath,QString tag,QString name,QString description,QString grid,QString zone,QString station,int type,bool inService,int state,QJsonObject connected_bus,QJsonObject label,QJsonObject context,int page_id,int op) { if(db.open()) @@ -864,15 +910,6 @@ void DataBase::readXML() pFile = NULL; } -DataBase* DataBase::GetInstance() -{ - if(instance == nullptr) - { - instance = new DataBase(); - } - return instance; -} - QJsonObject DataBase::QstringToJson(QString jsonString) { QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonString.toUtf8().data()); @@ -886,196 +923,251 @@ QJsonObject DataBase::QstringToJson(QString jsonString) //=================================元模=============================================// bool DataBase::getAttributeGroup() { - if(db.open()) - { - QSqlQuery qry(db); - bool success = qry.exec("SELECT * FROM basic.attribute_group"); - if (!success) { - qDebug()< DataBase::getProjectFromManager(const QString& sMeta) -{ - QMap map; - if(db.open()) - { - QSqlQuery qry(db); - - qry.prepare("SELECT tag,link_type FROM project_manager WHERE meta_model = ?"); - qry.bindValue(0,sMeta); - - bool res = qry.exec(); + bool res = qry.exec(strSQL); QString str = qry.lastQuery(); if(!res) { qDebug()< 0) + return true; + else + return false; + qry.clear(); } } - else + return false; + + /*try + { + executeSQL(strSQL); + return true; + } + catch (const std::exception& e) + { + return false; + }*/ +} + +bool DataBase::insertProjectManager(const QString& name,const QString& tag,const QString& metaModel,const QString& groupName,int linkType,QJsonObject checkState) +{ + QString strSQL = "INSERT INTO project_manager(name, tag, meta_model, group_name, link_type, check_state) VALUES (?, ?, ?, ?, ?, ?)"; + QJsonDocument checkDoc(checkState); + QString strCheck = checkDoc.toJson(QJsonDocument::Compact); + + QVariantList params; + params.append(name); + params.append(tag); + params.append(metaModel); + params.append(groupName); + params.append(linkType); + params.append(strCheck); + try + { + executeSQL(strSQL,false,params); + return true; + } + catch (const std::exception& e) + { + LOG_ERROR("DB", QString("Insert project_manager fail")); + return false; + } + +} + +bool DataBase::updateCheckState(const QString& tableName,QJsonObject checkState) +{ + QJsonDocument checkDoc(checkState); + QString strCheck = checkDoc.toJson(QJsonDocument::Compact); + + QString strSQL = "UPDATE project_manager SET check_state = ? WHERE name = ?"; + QVariantList params; + params.append(strCheck); + params.append(tableName); + + try + { + executeSQL(strSQL,false,params); + return true; + } + catch (const std::exception& e) + { + LOG_ERROR("DB", QString("Update table %1 state %2 fail").arg(tableName,strCheck)); + return false; + } +} + +QMap DataBase::getProjectFromManager(const QString& sMeta) +{ + QMap map; + QString strSQL = "SELECT tag,link_type FROM project_manager WHERE meta_model = ?"; + QVariantList params; + params.append(sMeta); + + try + { + QSqlQuery query = executeSQL(strSQL,false,params); + while (query.next()) + { + QString tag = query.value(0).toString(); + int nType = query.value(1).toInt(); + if(!map.contains(tag)) + { + map.insert(tag,nType); + } + query.clear(); + } return map; + } + catch (const std::exception& e) + { + return map; + } } QMap DataBase::getCheckStateFromManager(const QString& sProject) @@ -1191,95 +1295,133 @@ QMap DataBase::getCheckStateFromManager(const QString& sPro { return map; } - if(db.open()) - { - QSqlQuery qry(db); - qry.prepare("SELECT group_name, check_state FROM project_manager WHERE tag = ?"); - qry.bindValue(0,sProject); - bool res = qry.exec(); - QString str = qry.lastQuery(); - if(!res) + QString strSQL = "SELECT group_name, check_state FROM project_manager WHERE tag = ?"; + QVariantList params; + params.append(sProject); + + try + { + QSqlQuery query = executeSQL(strSQL,false,params); + while (query.next()) { - qDebug()< DataBase::getProjectTableName(const QString& sProject) { QMap map; - if(db.open()) - { - QSqlQuery qry(db); + QString strSQL = "SELECT group_name, name FROM project_manager WHERE tag = ?"; + QVariantList params; + params.append(sProject); - qry.prepare("SELECT group_name, name FROM project_manager WHERE tag = ?"); - qry.bindValue(0,sProject); - bool res = qry.exec(); - QString str = qry.lastQuery(); - if(!res) + try + { + QSqlQuery query = executeSQL(strSQL,false,params); + while (query.next()) { - qDebug()< DataBase::getAllProjectModel() +{ + QMap map; //工程模名,类型 + QString strSQL = "SELECT tag, MAX(link_type) AS link_type FROM project_manager GROUP BY tag"; + + try + { + QSqlQuery query = executeSQL(strSQL); + while (query.next()) + { + QString tableName = query.value(0).toString(); + int linkType = query.value(1).toInt(); + map.insert(tableName,linkType); + } + query.clear(); + return map; + } + catch (const std::exception& e) + { + return map; + } +} + +QMap DataBase::getProjectModelGroupInfo(const QString& sTable) +{ + QMap map; + QString strSQL = "SELECT * FROM project_manager WHERE tag = ?"; + QVariantList params; + params.append(sTable); + + try + { + QSqlQuery query = executeSQL(strSQL,false,params); + while (query.next()) + { + projectManager info; + info.id = query.value(0).toInt(); + info.name = query.value(1).toString(); + info.tag = query.value(2).toString(); + info.metaModel = query.value(3).toString(); + info.groupName = query.value(4).toString(); + info.linkType = query.value(5).toInt(); + QString json = query.value(6).toString(); + info.checkState = QstringToJson(json); + + if(!map.contains(info.groupName)) + map.insert(info.groupName,info); + } + query.clear(); + return map; + } + catch (const std::exception& e) + { + return map; + } } bool DataBase::createDynamicTable(const QString &tableName, const QStringList &fields) { - if(db.open()) - { - QString createTableSQL = "CREATE TABLE IF NOT EXISTS " + tableName + " ("; - - for (const QString &field : fields) { - createTableSQL += field + ", "; - } - - // Remove the last comma and space - createTableSQL.chop(2); - - createTableSQL += ");"; - - QSqlQuery query(db); - bool res = query.exec(createTableSQL); - if (!res) { - qDebug() << "Error creating dynamic table:" << query.lastError().text(); - } else { - qDebug() << "Dynamic table created successfully!"; - } - return res; + QString strSQL = "CREATE TABLE IF NOT EXISTS " + tableName + " ("; + for (const QString &field : fields) { + strSQL += field + ", "; + } + // Remove the last comma and space + strSQL.chop(2); + strSQL += ");"; + + try + { + executeSQL(strSQL,true); + LOG_INFO("DB", QString("Create table %1 success").arg(tableName)); + return true; + } + catch (const std::exception& e) + { + LOG_ERROR("DB", QString("Create table %1 fail").arg(tableName)); + return false; } - return false; } bool DataBase::deleteProjectModel(const QString& sProject) @@ -1288,151 +1430,153 @@ bool DataBase::deleteProjectModel(const QString& sProject) { return false; } - if(db.open()) + + QStringList lstTable; + QString strSQL = "SELECT name FROM project_manager WHERE tag = ?"; + QVariantList params; + params.append(sProject); + try { - QStringList lstTable; - QSqlQuery qry(db); - - qry.prepare("SELECT name FROM project_manager WHERE tag = ?"); - qry.bindValue(0,sProject); - bool res = qry.exec(); - QString str = qry.lastQuery(); - if(!res) + QSqlQuery query = executeSQL(strSQL,false,params); + while (query.next()) { - qDebug()< mOld,QMap mNew) { - if(db.open()) - { - QSqlQuery query(db); - QStringList sqlBatch; - - for (auto &col : mOld.keys()) { - if (!mNew.contains(col)) { - sqlBatch << QString("ALTER TABLE %1 DROP COLUMN %2") - .arg(sTable, col); - } + QStringList sqlStatements; + for (auto &col : mOld.keys()) { + if (!mNew.contains(col)) { + sqlStatements << QString("ALTER TABLE %1 DROP COLUMN %2") + .arg(sTable, col); } - - // 添加/修改列 - for (auto &col : mNew.keys()) { - const QString &newType = mNew[col]; - - // 新增列 - if (!mOld.contains(col)) { - sqlBatch << QString("ALTER TABLE %1 ADD COLUMN %2 %3") - .arg(sTable, col, newType); - } - // 修改列类型 - else if (mOld[col] != newType) { - sqlBatch << QString("ALTER TABLE %1 ALTER COLUMN %2 TYPE %3 USING %2::%3") - .arg(sTable, col, newType); - } - } - - // ================= 阶段4:执行变更事务 ================= - if (!db.transaction()) { - qDebug() << "开启事务失败:" << db.lastError().text(); - return false; - } - - for (const QString &sql : sqlBatch) { - if (!query.exec(sql)) { - qDebug() << "执行SQL失败:" << query.lastError().text() - << "\n语句:" << sql; - db.rollback(); - return false; - } - } - - if (!db.commit()) { - qDebug() << "提交事务失败:" << db.lastError().text(); - db.rollback(); - return false; - } - - return true; } - else + // 添加/修改列 + for (auto &col : mNew.keys()) { + const QString &newType = mNew[col]; + + // 新增列 + if (!mOld.contains(col)) { + sqlStatements << QString("ALTER TABLE %1 ADD COLUMN %2 %3") + .arg(sTable, col, newType); + } + // 修改列类型 + else if (mOld[col] != newType) { + sqlStatements << QString("ALTER TABLE %1 ALTER COLUMN %2 TYPE %3 USING %2::%3") + .arg(sTable, col, newType); + } + } + + if(!db.transaction()) + { + LOG_ERROR("DB", QString("Start transaction failed. error: %1.").arg( db.lastError().databaseText())); return false; + } + try + { + executeBatchSQL(sqlStatements); + } + catch (const std::exception& e) + { + if(!db.rollback()) // 回滚失败时记录警告 + { + LOG_ERROR("DB", QString("Rollback failed. error: %1").arg(db.lastError().databaseText())); + } + return false; + } + if(!db.commit()) // 提交 + { + LOG_ERROR("DB", QString("Commit transaction failed. error: %1.").arg(db.lastError().databaseText())); + return false; + } + return true; } diff --git a/diagramUtils/source/logger.cpp b/diagramUtils/source/logger.cpp new file mode 100644 index 0000000..d10d027 --- /dev/null +++ b/diagramUtils/source/logger.cpp @@ -0,0 +1,155 @@ +#include "logger.h" +#include +#include +#include +#include + +Logger& Logger::instance() +{ + //采用静态局部变量的方式,静态局部变量的初始化是在第一次访问时,以后的调用不会多次初始化,并且生命周期和程序一致 + static Logger instance; + return instance; +} + +Logger::Logger() +{ + initialize(); +} + +Logger::~Logger() +{ + shutdown(); +} + +void Logger::initialize() +{ + //默认配置 + m_logFilePath = ""; + m_logLevel = INFO; + m_maxFileSize = 1024 *1024 * 10; //10MB + m_maxBackupFiles = 5; + m_outputToConsole = true; + m_outputOtFile = true; + //从配置文件中加载配置 + loadConfig(); +} + +void Logger::loadConfig(/*const QString& configFilePath*/) +{ + //QString filePath = Settings::instance().value("Log", "logFile").toString(); + QString filePath = QApplication::applicationDirPath(); + setLogFile(filePath); + + /*QString strLevel = Settings::instance().value("Log", "level").toString().toUpper(); + if(strLevel == "DEBUG") + m_logLevel = DEBUG; + else if(strLevel == "INFO") + m_logLevel = INFO; + else if(strLevel == "WARNING") + m_logLevel = WARNING; + else if(strLevel == "ERROR") + m_logLevel = ERROR; + else if(strLevel == "FATAL") + m_logLevel = FATAL; + + m_maxFileSize = Settings::instance().value("Log", "maxSize").toLongLong(); + m_maxBackupFiles = Settings::instance().value("Log", "backups").toInt(); + QString strOutputToConsole = Settings::instance().value("Log", "consoleOutput").toString(); + if(strOutputToConsole == "true") + m_outputToConsole = true; + else + m_outputToConsole = false; + QString strOutputToFile = Settings::instance().value("Log", "fileOutput").toString(); + if(strOutputToFile == "true") + m_outputOtFile = true; + else + m_outputOtFile = false;*/ +} + +void Logger::setLogFile(const QString& filePath) +{ + //检查目录文件所在目录,如果不存在则创建目录 + QFileInfo fileInfo(filePath); + QDir logDir = fileInfo.dir(); + if(!logDir.exists()) + logDir.mkpath("."); + + //更新log文件前要先关闭当前已打开的文件 + if(m_logFile.isOpen()) + m_logFile.close(); + + m_logFilePath = filePath; + m_logFile.setFileName(filePath); +} + +void Logger::shutdown() +{ + if(m_logFile.isOpen()) + m_logFile.close(); +} + +void Logger::writeToFile(const QString& message) +{ + if(m_logFilePath.isEmpty()) + return; + + if(!m_logFile.isOpen()) + { + if (!m_logFile.open(QIODevice::Append | QIODevice::Text)) + { + qWarning() << "Failed to open log file:" << m_logFile.errorString(); + return; + } + //打开文件时先键入一个换行符 + QTextStream stream(&m_logFile); + stream << Qt::endl; + stream.flush(); //刷新输出缓冲区,确保数据立即写入文件 + } + + QTextStream stream(&m_logFile); + stream << message << Qt::endl; + stream.flush(); //刷新输出缓冲区,确保数据立即写入文件 + + if(m_logFile.size() > m_maxFileSize) + rollLogFiles(); +} + +void Logger::rollLogFiles() +{ + if(m_logFile.isOpen()) + m_logFile.close(); + + //删除最旧的备份文件(备份文件以‘日志文件.数字’的格式命名,数字越大表示文件越旧) + QFile::remove(QString("%1.%2").arg(m_logFilePath).arg(m_maxBackupFiles)); + //剩余文件依次更改名称 + for(int i = m_maxBackupFiles - 1; i > 0; i--) + QFile::rename(QString("%1.%2").arg(m_logFilePath).arg(i), QString("%1.%2").arg(m_logFilePath).arg(i + 1)); + //将当前日志文件更改为'最新'的备份文件(编号为1) + QFile::rename(m_logFilePath, QString("%1.1").arg(m_logFilePath)); + //更新当前配置文件(重新打开) + m_logFile.setFileName(m_logFilePath); + if (!m_logFile.open(QIODevice::Append | QIODevice::Text)) + qWarning() << "Failed to open new log file after rolling:" << m_logFile.errorString(); +} + +QString Logger::formatLogMessage(LogLevel level, const QString& context, const QString& message) +{ + static const char* levelStrings[] = {"FATAL", "ERROR", "WARNING", "INFO", "DEBUG"}; + return QString("[%1] [%2] [%3] %4") + .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")) + .arg(levelStrings[level]) + .arg(context) + .arg(message); +} + +void Logger::log(LogLevel level, const QString& context, const QString& message) +{ + if(level > m_logLevel) + return; + + QString formatMessage = formatLogMessage(level, context, message); + if(m_outputToConsole) + QTextStream(stderr) << formatMessage << Qt::endl; + if(m_outputOtFile) + writeToFile(formatMessage); +} diff --git a/include/electricElementsBox.h b/include/electricElementsBox.h index 177c11f..1e68dd7 100644 --- a/include/electricElementsBox.h +++ b/include/electricElementsBox.h @@ -19,6 +19,7 @@ public: public: void initial(); ToolBox* getToolBox() const; + void updateProjectModelItemList(); //更新工程模对象列表 signals: void addEletricItem(GraphicsItemType&); public slots: diff --git a/source/electricElementsBox.cpp b/source/electricElementsBox.cpp index 8afb742..65d50ed 100644 --- a/source/electricElementsBox.cpp +++ b/source/electricElementsBox.cpp @@ -1,9 +1,9 @@ #include - #include "electricElementsPanel.h" #include "electricElementsBox.h" #include "toolBox.h" #include "util/baseSelector.h" +#include "dataBase.h" ElectricElementsBox::ElectricElementsBox(QObject *parent) : QObject(parent), @@ -46,6 +46,11 @@ ToolBox* ElectricElementsBox::getToolBox() const return m_pToolBox; } +void ElectricElementsBox::updateProjectModelItemList() +{ + QMap model = DataBase::GetInstance()->getAllProjectModel(); +} + void ElectricElementsBox::onSignal_addEletricItem(GraphicsItemType& type) { emit addEletricItem(type); diff --git a/source/projectModelDlg.cpp b/source/projectModelDlg.cpp index b06c4cd..1a6135e 100644 --- a/source/projectModelDlg.cpp +++ b/source/projectModelDlg.cpp @@ -537,7 +537,7 @@ void projectModelDlg::onDeleteProjectClicked() //============================================================================= QStringList projectModelDlg::getModelList() const { - QMap modelMap = DataBase::GetInstance()->ModelAttribute(); + QMap modelMap = DataBase::GetInstance()->ModelType(); QSet modelSet; for(auto &model:modelMap) @@ -550,68 +550,76 @@ QStringList projectModelDlg::getModelList() const QStringList projectModelDlg::getGroupList(const QString& sM) const { + QMap modelType = DataBase::GetInstance()->ModelType(); + QMap modelGroupMap = DataBase::GetInstance()->ModelGroup(); QMap groupMap = DataBase::GetInstance()->AttributeGroup(); - QMap modelMap = DataBase::GetInstance()->ModelAttribute(); - QMap attMap = DataBase::GetInstance()->Attribute(); - QSet groupSet; - QStringList groupList; - for(auto &model:modelMap) //遍历获取属性组id + int metaId = 0; + for(auto &meta:modelType) { - if(model.modelType == sM) + if(sM == meta.modelType) //查找元模对应的id { - int attId = model.attributeId; - groupSet.insert(attMap[attId].attributeGroup); + metaId = meta.id; + break; } } - for(auto &id:groupSet) //取得id对应的组名 + QList lstGroupId; + for(auto &group:modelGroupMap) //找到元模id对应的属性组id { - groupList.append(groupMap[id].group); + if(group.modelTypeId == metaId) + { + lstGroupId.push_back(group.attributeGroupId); + } } + + QStringList groupList; + for(auto &id:lstGroupId) //从属性组中找到id对应的组名 + { + groupList.append(groupMap[id].groupType); + } + return groupList; } QStringList projectModelDlg::getAttributeList(const QString& sM,const QString& sG) const { + QMap modelType = DataBase::GetInstance()->ModelType(); + //QMap modelGroupMap = DataBase::GetInstance()->ModelGroup(); QMap groupMap = DataBase::GetInstance()->AttributeGroup(); - QMap modelMap = DataBase::GetInstance()->ModelAttribute(); + QMap modelAttMap = DataBase::GetInstance()->ModelAttribute(); QMap attMap = DataBase::GetInstance()->Attribute(); - int groupId = -1; - for(auto &group:groupMap) + int metaId = -1; + for(auto &meta:modelType) { - if(group.group == sG) //根据group获取对应Id + if(sM == meta.modelType) //查找元模对应的id { - groupId = group.id; + metaId = meta.id; break; } } - QSet attSet; - QStringList attList; - if(groupId != -1) + int groupId = -1; + for(auto &attGroup:groupMap) { - for(auto &model:modelMap) //获取当前模型,当前属性组下的属性 + if(attGroup.groupType == sG) //返回参数属性组名对应的id { - if(model.modelType == sM) - { - int attId = model.attributeId; - if(attMap[attId].attributeGroup == groupId) //当前属性的属性组id等于选定的属性组id - { - attSet.insert(model.attributeId); - } - } + groupId = attGroup.id; + break; } - - for(auto &id:attSet) //取得id对应的组名 - { - attList.append(attMap[id].attribute); - } - return attList; } - return QStringList(); + QStringList lst; + for(auto &mt:modelAttMap) + { + if(mt.modelTypeId == metaId && mt.attributeGroupId == groupId) + { + lst.append(attMap[mt.attributeId].attribute); + } + } + + return lst; } void projectModelDlg::setItemAttribute(const QString& name,QStandardItem* p) @@ -621,19 +629,18 @@ void projectModelDlg::setItemAttribute(const QString& name,QStandardItem* p) for(auto &att:attMap) { - QString sType = dt[att.dataType].dataType; //获得属性id对应的属性名 + QString sType = dt[att.dataTypeId].dataType; //获得属性id对应的属性名 if(name == att.attribute) { p->setData(att.id,Id); p->setData(att.attribute,Attribute); - p->setData(sType,DataType); + p->setData(att.attributeName,AttributeName); + p->setData(sType,DataType); //不直接使用id,拼接完成str p->setData(att.lengthPrecision,LengthPrecision); p->setData(att.scale,Scale); + p->setData(att.isNotNull,IsNotNull); p->setData(att.defaultValue,DefaultValue); p->setData(att.valueRange,ValueRange); - p->setData(att.attributeGroup,AttributeGroup); - p->setData(att.isNotNull,IsNotNull); - p->setData(att.isIndex,IsIndex); return; } } @@ -641,6 +648,8 @@ void projectModelDlg::setItemAttribute(const QString& name,QStandardItem* p) QPair projectModelDlg::combinePropertySql(const QStandardItem* pItem) { + QMap dt = DataBase::GetInstance()->DataType(); + int id = pItem->data(Id).toInt(); QString attribute = pItem->data(Attribute).toString(); QString dataType = pItem->data(DataType).toString(); @@ -648,9 +657,7 @@ QPair projectModelDlg::combinePropertySql(const QStandardItem* int scale = pItem->data(Scale).toInt(); QString defaultValue = pItem->data(DefaultValue).toString(); QString valueRange = pItem->data(ValueRange).toString(); - int attributeGroup = pItem->data(AttributeGroup).toInt(); int isNotNull = pItem->data(IsNotNull).toInt(); - int isIndex = pItem->data(IsIndex).toInt(); bool needsQuotes = stringDataTypes.contains(dataType); // 处理数据类型及其长度精度