From b55596078de8fdeaa9deee0953fa5ea02e2daa1b Mon Sep 17 00:00:00 2001 From: taocong Date: Thu, 28 May 2026 19:44:36 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=83=E6=95=B0=E6=8D=AE=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E6=9B=B4=E6=96=B0UF20=E3=80=81UFT30=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Uft30ChangeCode.pro | 8 + src/metadataupdate/filedb.cpp | 15 + src/metadataupdate/filedb.h | 20 ++ src/metadataupdate/metadatacli.cpp | 47 +++ src/metadataupdate/metadataprocessor.cpp | 339 ++++++++++++++++++ src/metadataupdate/metadataprocessor.h | 33 ++ src/metadataupdate/uf2interface.cpp | 280 +++++++++++++++ src/metadataupdate/uf2interface.h | 62 ++++ src/metadataupdate/uft3interface.cpp | 240 +++++++++++++ src/metadataupdate/uft3interface.h | 39 ++ src/pages/metadatupdate/metadatupdatepage.cpp | 133 ++++++- src/pages/metadatupdate/metadatupdatepage.h | 21 ++ src/utils/logmanager.cpp | 6 +- 13 files changed, 1238 insertions(+), 5 deletions(-) create mode 100644 src/metadataupdate/filedb.cpp create mode 100644 src/metadataupdate/filedb.h create mode 100644 src/metadataupdate/metadatacli.cpp create mode 100644 src/metadataupdate/metadataprocessor.cpp create mode 100644 src/metadataupdate/metadataprocessor.h create mode 100644 src/metadataupdate/uf2interface.cpp create mode 100644 src/metadataupdate/uf2interface.h create mode 100644 src/metadataupdate/uft3interface.cpp create mode 100644 src/metadataupdate/uft3interface.h diff --git a/Uft30ChangeCode.pro b/Uft30ChangeCode.pro index 46573c6..023e952 100644 --- a/Uft30ChangeCode.pro +++ b/Uft30ChangeCode.pro @@ -16,6 +16,10 @@ SOURCES += main.cpp \ src/pages/help/helppage.cpp \ src/pages/settings/settingspage.cpp \ src/pages/metadatupdate/metadatupdatepage.cpp \ + src/metadataupdate/filedb.cpp \ + src/metadataupdate/uf2interface.cpp \ + src/metadataupdate/uft3interface.cpp \ + src/metadataupdate/metadataprocessor.cpp \ src/utils/datacache.cpp \ src/utils/uf2configreader.cpp \ src/utils/uft3configreader.cpp \ @@ -31,6 +35,10 @@ HEADERS += src/mainwindow/mainwindow.h \ src/pages/help/helppage.h \ src/pages/settings/settingspage.h \ src/pages/metadatupdate/metadatupdatepage.h \ + src/metadataupdate/filedb.h \ + src/metadataupdate/uf2interface.h \ + src/metadataupdate/uft3interface.h \ + src/metadataupdate/metadataprocessor.h \ src/utils/datacache.h \ src/utils/uf2configreader.h \ src/utils/uft3configreader.h \ diff --git a/src/metadataupdate/filedb.cpp b/src/metadataupdate/filedb.cpp new file mode 100644 index 0000000..85d1604 --- /dev/null +++ b/src/metadataupdate/filedb.cpp @@ -0,0 +1,15 @@ +#include "filedb.h" + +FileDB* FileDB::m_instance = nullptr; + +FileDB::FileDB(QObject *parent) : QObject(parent) +{ +} + +FileDB* FileDB::instance() +{ + if (!m_instance) { + m_instance = new FileDB(); + } + return m_instance; +} \ No newline at end of file diff --git a/src/metadataupdate/filedb.h b/src/metadataupdate/filedb.h new file mode 100644 index 0000000..ad95954 --- /dev/null +++ b/src/metadataupdate/filedb.h @@ -0,0 +1,20 @@ +#ifndef FILEDB_H +#define FILEDB_H + +#include +#include + +class FileDB : public QObject +{ + Q_OBJECT +public: + static FileDB* instance(); + + QStringList uft3RealFunctionList; + +private: + explicit FileDB(QObject *parent = nullptr); + static FileDB* m_instance; +}; + +#endif // FILEDB_H \ No newline at end of file diff --git a/src/metadataupdate/metadatacli.cpp b/src/metadataupdate/metadatacli.cpp new file mode 100644 index 0000000..64168f6 --- /dev/null +++ b/src/metadataupdate/metadatacli.cpp @@ -0,0 +1,47 @@ +#include "uf2interface.h" +#include "uft3interface.h" +#include "filedb.h" +#include +#include +#include +#include +#include +#include +#include + +QJsonObject interfaceInfoToJson(const InterfaceInfo& info) +{ + QJsonObject obj; + obj["cname"] = info.cname; + obj["eName"] = info.eName; + obj["functionNo"] = info.functionNo; + obj["flag"] = info.flag; + obj["path"] = info.path; + obj["code"] = info.code; + obj["id"] = info.id; + obj["sysStatus"] = info.sysStatus; + obj["description"] = info.description; + obj["moudle"] = info.moudle; + obj["moudleEName"] = info.moudleEName; + obj["serverType"] = info.serverType; + obj["returnResultSet"] = info.returnResultSet; + obj["needTransMonitor"] = info.needTransMonitor; + obj["checkLicence"] = info.checkLicence; + + QJsonObject inputFields; + for (const QString& key : info.inputFields.keys()) { + QJsonObject field; + field["name"] = info.inputFields[key].name; + field["flag"] = info.inputFields[key].flag; + field["desc"] = info.inputFields[key].desc; + field["uuid"] = info.inputFields[key].uuid; + inputFields[key] = field; + } + obj["inputFields"] = inputFields; + + QJsonObject outputFields; + for (const QString& key : info.outputFields.keys()) { + QJsonObject field; + field["name"] = info.outputFields[key].name; + field["flag"] = info.outputFields[key].flag; + field["desc"] = info \ No newline at end of file diff --git a/src/metadataupdate/metadataprocessor.cpp b/src/metadataupdate/metadataprocessor.cpp new file mode 100644 index 0000000..54aac7f --- /dev/null +++ b/src/metadataupdate/metadataprocessor.cpp @@ -0,0 +1,339 @@ +#include "metadataprocessor.h" +#include "uf2interface.h" +#include "uft3interface.h" +#include "filedb.h" +#include "utils/logmanager.h" +#include +#include +#include +#include + +MetadataProcessor::MetadataProcessor(QObject *parent) : QObject(parent) +{ +} + +bool MetadataProcessor::isValidUtf8(const QByteArray& data) +{ + QString test = QString::fromUtf8(data); + return test.toUtf8() == data; +} + +QString MetadataProcessor::readConfig(const QString& section, const QString& key, const QString& basePath) +{ + QString uf2touft3Path = QDir(basePath).filePath("uf2touft3"); + QString configPath = QDir(uf2touft3Path).filePath("config.ini"); + + QFile file(configPath); + if (!file.open(QIODevice::ReadOnly)) { + LogManager::instance()->logError(QString("无法打开配置文件: %1").arg(configPath)); + return QString(); + } + + QByteArray data = file.readAll(); + file.close(); + + QString content; + if (isValidUtf8(data)) { + content = QString::fromUtf8(data); + } else { + content = QString::fromLocal8Bit(data); + } + + QString sectionPattern = QString("\\[%1\\]").arg(section); + QString keyPattern = QString("^%1\\s*=\\s*(.+)$").arg(key); + + QRegularExpression sectionRegex(sectionPattern); + QRegularExpression keyRegex(keyPattern, QRegularExpression::MultilineOption); + + int sectionPos = content.indexOf(sectionRegex); + if (sectionPos == -1) { + return QString(); + } + + int nextSectionPos = content.indexOf(QRegularExpression("\\["), sectionPos + 1); + QString sectionContent; + if (nextSectionPos == -1) { + sectionContent = content.mid(sectionPos); + } else { + sectionContent = content.mid(sectionPos, nextSectionPos - sectionPos); + } + + QRegularExpressionMatch match = keyRegex.match(sectionContent); + if (match.hasMatch()) { + QString value = match.captured(1).trimmed(); + value.replace("\\", "/"); + return value; + } + + return QString(); +} + +bool MetadataProcessor::writeJson(const QString& filePath, const QJsonObject& jsonObject) +{ + QFile file(filePath); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + LogManager::instance()->logError(QString("无法打开文件: %1").arg(filePath)); + return false; + } + + QJsonDocument doc(jsonObject); + file.write(doc.toJson(QJsonDocument::Indented)); + file.close(); + return true; +} + +QJsonObject MetadataProcessor::readJson(const QString& filePath) +{ + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + LogManager::instance()->logError(QString("无法打开文件: %1").arg(filePath)); + return QJsonObject(); + } + + QByteArray data = file.readAll(); + QJsonDocument doc = QJsonDocument::fromJson(data); + file.close(); + + if (doc.isNull()) { + LogManager::instance()->logError(QString("无效的 JSON 文件: %1").arg(filePath)); + return QJsonObject(); + } + + return doc.object(); +} + +QString MetadataProcessor::getBasePath() const +{ + return m_basePath; +} + +void MetadataProcessor::setBasePath(const QString& path) +{ + m_basePath = path; +} + +bool MetadataProcessor::processUf2Interfaces(const QString& basePath) +{ + LogManager::instance()->log("========== 开始处理 UF2.0 接口 =========="); + LogManager::instance()->log(QString("基础路径(basePath): %1").arg(basePath)); + + QString uf2touft3Path = QDir(basePath).filePath("uf2touft3"); + QString configPath = QDir(uf2touft3Path).filePath("config.ini"); + LogManager::instance()->log(QString("配置文件路径: %1").arg(configPath)); + + QStringList completeNameList = {"module.xml", ".project", "冲突检测.wlua"}; + QStringList containNameList = {".vbusiness", "/公共资源/", "/数据库/", "/脚本/", "/通用数据/", "/.svn/"}; + + QMap filterDict; + filterDict["completeNameList"] = completeNameList; + filterDict["containNameList"] = containNameList; + + QString dirPath = readConfig("projectPath", "uf20", basePath); + QString ufAcct20ProjectDir = readConfig("projectPath", "ufAcct20", basePath); + QString uftDbSett = readConfig("projectPath", "UftdbSett", basePath); + + QString supportUftdbSett = readConfig("testConfig", "supportUftdbSett", basePath); + if (supportUftdbSett == "0") { + uftDbSett.clear(); + } + + LogManager::instance()->log(QString("UF20 项目路径: %1").arg(dirPath)); + LogManager::instance()->log(QString("UF20 会计项目路径: %1").arg(ufAcct20ProjectDir)); + LogManager::instance()->log(QString("UFT 数据库设置路径: %1").arg(uftDbSett)); + + QString custJsonPath = QDir(uf2touft3Path).filePath("cust.json"); + LogManager::instance()->log(QString("客户配置文件路径: %1").arg(custJsonPath)); + QJsonObject custJson = readJson(custJsonPath); + + Uf2Interface uf2; + QMap resultMap = uf2.scanDir(dirPath, ufAcct20ProjectDir, uftDbSett, filterDict); + + QJsonObject resultJson; + for (const QString& key : resultMap.keys()) { + const InterfaceInfo& info = resultMap[key]; + + QJsonObject interfaceJson; + interfaceJson["cname"] = info.cname; + interfaceJson["eName"] = info.eName; + interfaceJson["functionNo"] = info.functionNo; + interfaceJson["flag"] = info.flag; + interfaceJson["path"] = info.path; + interfaceJson["code"] = info.code; + interfaceJson["moudle"] = info.moudle; + interfaceJson["moudleEName"] = info.moudleEName; + interfaceJson["serverType"] = info.serverType; + interfaceJson["returnResultSet"] = info.returnResultSet; + interfaceJson["needTransMonitor"] = info.needTransMonitor; + interfaceJson["checkLicence"] = info.checkLicence; + + QJsonObject inputFieldsJson; + for (const QString& fieldName : info.inputFields.keys()) { + const FieldInfo& field = info.inputFields[fieldName]; + QJsonObject fieldJson; + fieldJson["name"] = field.name; + fieldJson["flag"] = field.flag; + fieldJson["desc"] = field.desc; + inputFieldsJson[fieldName] = fieldJson; + } + interfaceJson["inputFileds"] = inputFieldsJson; + + QJsonObject outputFieldsJson; + for (const QString& fieldName : info.outputFields.keys()) { + const FieldInfo& field = info.outputFields[fieldName]; + QJsonObject fieldJson; + fieldJson["name"] = field.name; + fieldJson["flag"] = field.flag; + fieldJson["desc"] = field.desc; + outputFieldsJson[fieldName] = fieldJson; + } + interfaceJson["outputFileds"] = outputFieldsJson; + + QJsonObject variableFieldsJson; + for (const QString& fieldName : info.variableFields.keys()) { + const FieldInfo& field = info.variableFields[fieldName]; + QJsonObject fieldJson; + fieldJson["name"] = field.name; + fieldJson["cname"] = field.cname; + fieldJson["hsType"] = field.hsType; + fieldJson["desc"] = field.desc; + variableFieldsJson[fieldName] = fieldJson; + } + interfaceJson["variableFileds"] = variableFieldsJson; + + resultJson[key] = interfaceJson; + } + + QString outputPath = QDir(uf2touft3Path).filePath("uf2.json"); + LogManager::instance()->log(QString("输出文件路径(uf2.json): %1").arg(outputPath)); + + if (!writeJson(outputPath, resultJson)) { + return false; + } + + LogManager::instance()->log(QString("UF2.0 接口处理完成,结果已保存到: %1").arg(outputPath)); + if (!resultMap.isEmpty()) { + QString firstKey = resultMap.keys().first(); + LogManager::instance()->log(QString("示例功能号: %1").arg(resultMap[firstKey].functionNo)); + } + + return true; +} + +bool MetadataProcessor::processUft3Interfaces(const QString& basePath) +{ + LogManager::instance()->log("========== 开始处理 UFT3.0 接口 =========="); + LogManager::instance()->log(QString("基础路径(basePath): %1").arg(basePath)); + + QString uf2touft3Path = QDir(basePath).filePath("uf2touft3"); + QString configPath = QDir(uf2touft3Path).filePath("config.ini"); + LogManager::instance()->log(QString("配置文件路径: %1").arg(configPath)); + + QString moduleGenerationCheck = readConfig("testConfig", "moduleGenerationCheck", basePath); + LogManager::instance()->log(QString("模块生成检查: %1").arg(moduleGenerationCheck)); + + QStringList completeNameList = {"module.xml", "project.xml", "冲突检测.wlua"}; + QStringList containNameList = {".extinterface", ".uftatomfunction", ".uftatomservice", ".uftfunction", ".uftservice"}; + + QMap filterDict; + filterDict["completeNameList"] = completeNameList; + filterDict["containNameList"] = containNameList; + + QString dirPath = readConfig("projectPath", "uft30", basePath); + LogManager::instance()->log(QString("UFT30 项目路径: %1").arg(dirPath)); + + Uft3Interface uft3; + auto result = uft3.scanDir(dirPath, filterDict, moduleGenerationCheck); + + QMap resultMap = result.first; + QMap transCodeMap = result.second; + + QJsonObject resultJson; + for (const QString& key : resultMap.keys()) { + const InterfaceInfo& info = resultMap[key]; + + QJsonObject interfaceJson; + interfaceJson["cname"] = info.cname; + interfaceJson["eName"] = info.eName; + interfaceJson["functionNo"] = info.functionNo; + interfaceJson["flag"] = info.flag; + interfaceJson["path"] = info.path; + interfaceJson["code"] = info.code; + interfaceJson["id"] = info.id; + interfaceJson["sysStatus"] = info.sysStatus; + interfaceJson["description"] = info.description; + interfaceJson["moudle"] = info.moudle; + + QJsonObject inputFieldsJson; + for (const QString& fieldName : info.inputFields.keys()) { + const FieldInfo& field = info.inputFields[fieldName]; + QJsonObject fieldJson; + fieldJson["name"] = field.name; + fieldJson["flag"] = field.flag; + fieldJson["desc"] = field.desc; + fieldJson["uuid"] = field.uuid; + inputFieldsJson[fieldName] = fieldJson; + } + interfaceJson["inputFileds"] = inputFieldsJson; + + QJsonObject outputFieldsJson; + for (const QString& fieldName : info.outputFields.keys()) { + const FieldInfo& field = info.outputFields[fieldName]; + QJsonObject fieldJson; + fieldJson["name"] = field.name; + fieldJson["flag"] = field.flag; + fieldJson["desc"] = field.desc; + fieldJson["paramType"] = field.paramType; + fieldJson["uuid"] = field.uuid; + outputFieldsJson[fieldName] = fieldJson; + } + interfaceJson["outputFileds"] = outputFieldsJson; + + QJsonObject internalFieldsJson; + for (const QString& fieldName : info.internalFields.keys()) { + const FieldInfo& field = info.internalFields[fieldName]; + QJsonObject fieldJson; + fieldJson["name"] = field.name; + fieldJson["type"] = field.type; + fieldJson["desc"] = field.desc; + fieldJson["paramType"] = field.paramType; + fieldJson["uuid"] = field.uuid; + internalFieldsJson[fieldName] = fieldJson; + } + interfaceJson["internalFileds"] = internalFieldsJson; + + resultJson[key] = interfaceJson; + } + + QString outputPath = QDir(uf2touft3Path).filePath("uft3.json"); + LogManager::instance()->log(QString("输出文件路径(uft3.json): %1").arg(outputPath)); + + if (!writeJson(outputPath, resultJson)) { + return false; + } + + QJsonObject transCodeJson; + for (const QString& key : transCodeMap.keys()) { + const InterfaceInfo& info = transCodeMap[key]; + + QJsonObject interfaceJson; + interfaceJson["cname"] = info.cname; + interfaceJson["eName"] = info.eName; + interfaceJson["functionNo"] = info.functionNo; + interfaceJson["flag"] = info.flag; + interfaceJson["path"] = info.path; + interfaceJson["code"] = info.code; + transCodeJson[key] = interfaceJson; + } + + QString transOutputPath = QDir(uf2touft3Path).filePath("uft3Trans.json"); + LogManager::instance()->log(QString("输出文件路径(uft3Trans.json): %1").arg(transOutputPath)); + + if (!writeJson(transOutputPath, transCodeJson)) { + return false; + } + + LogManager::instance()->log(QString("UFT3.0 接口处理完成,结果已保存到: %1").arg(outputPath)); + LogManager::instance()->log(QString("交易码结果已保存到: %1").arg(transOutputPath)); + + return true; +} \ No newline at end of file diff --git a/src/metadataupdate/metadataprocessor.h b/src/metadataupdate/metadataprocessor.h new file mode 100644 index 0000000..0501936 --- /dev/null +++ b/src/metadataupdate/metadataprocessor.h @@ -0,0 +1,33 @@ +#ifndef METADATAPROCESSOR_H +#define METADATAPROCESSOR_H + +#include +#include +#include +#include +#include + +struct InterfaceInfo; + +class MetadataProcessor : public QObject +{ + Q_OBJECT +public: + explicit MetadataProcessor(QObject *parent = nullptr); + + bool processUf2Interfaces(const QString& basePath); + bool processUft3Interfaces(const QString& basePath); + + QString getBasePath() const; + void setBasePath(const QString& path); + +private: + bool isValidUtf8(const QByteArray& data); + QString readConfig(const QString& section, const QString& key, const QString& basePath); + bool writeJson(const QString& filePath, const QJsonObject& jsonObject); + QJsonObject readJson(const QString& filePath); + + QString m_basePath; +}; + +#endif // METADATAPROCESSOR_H \ No newline at end of file diff --git a/src/metadataupdate/uf2interface.cpp b/src/metadataupdate/uf2interface.cpp new file mode 100644 index 0000000..f9db034 --- /dev/null +++ b/src/metadataupdate/uf2interface.cpp @@ -0,0 +1,280 @@ +#include "uf2interface.h" +#include "utils/logmanager.h" +#include +#include +#include +#include +#include +#include + +Uf2Interface::Uf2Interface(QObject *parent) : QObject(parent) +{ +} + +InterfaceInfo Uf2Interface::loadInterface(const QString& filePath) +{ + InterfaceInfo result; + result.path = filePath; + + QString sFilePath = filePath; + sFilePath.replace('\\', '/'); + + QFileInfo fileInfo(sFilePath); + if (!fileInfo.exists()) { + LogManager::instance()->logError(QString("%1 文件不存在!").arg(sFilePath)); + return result; + } + + QString sCodeName = fileInfo.baseName(); + result.cname = sCodeName; + + QFile file(sFilePath); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + LogManager::instance()->logError(QString("%1 无法打开文件").arg(sFilePath)); + return result; + } + + QXmlStreamReader xml(&file); + QStack elementStack; + + while (!xml.atEnd() && !xml.hasError()) { + QXmlStreamReader::TokenType token = xml.readNext(); + + if (token == QXmlStreamReader::StartElement) { + QString elementName = xml.name().toString(); + elementStack.push(elementName); + + if (elementName == "basic") { + QXmlStreamAttributes attrs = xml.attributes(); + if (attrs.hasAttribute("englishName")) { + result.eName = attrs.value("englishName").toString(); + } + if (attrs.hasAttribute("objectId")) { + result.functionNo = attrs.value("objectId").toString(); + } + if (attrs.hasAttribute("flag")) { + result.flag = attrs.value("flag").toString(); + } + if (attrs.hasAttribute("checkLicence")) { + result.checkLicence = (attrs.value("checkLicence").toString() == "true"); + } + if (attrs.hasAttribute("returnResultSet")) { + result.returnResultSet = (attrs.value("returnResultSet").toString() == "true"); + } + if (attrs.hasAttribute("needTransMonitor")) { + result.needTransMonitor = (attrs.value("needTransMonitor").toString() == "true"); + } + } + else if (elementName == "stdFieldQuote") { + QXmlStreamAttributes attrs = xml.attributes(); + + QString parentName = elementStack.size() > 1 ? elementStack[elementStack.size() - 2] : QString(); + + FieldInfo field; + field.name = attrs.value("name").toString(); + field.flag = attrs.value("flag").toString(); + field.desc = attrs.value("comment").toString(); + + if (parentName == "import") { + result.inputFields[field.name] = field; + } else if (parentName == "export") { + result.outputFields[field.name] = field; + if (field.flag.contains("IO")) { + result.inputFields[field.name] = field; + } + } + } + else if (elementName == "variableField") { + QXmlStreamAttributes attrs = xml.attributes(); + FieldInfo field; + field.name = attrs.value("name").toString(); + field.cname = attrs.value("cname").toString(); + field.hsType = attrs.value("type").toString(); + field.desc = attrs.value("desc").toString(); + result.variableFields[field.name] = field; + } + } + else if (token == QXmlStreamReader::EndElement) { + if (!elementStack.isEmpty()) { + elementStack.pop(); + } + + QString elementName = xml.name().toString(); + if (elementName == "code") { + result.code = xml.text().toString(); + if (filePath.contains("不用编译")) { + result.code.clear(); + } + } + } + } + + file.close(); + return result; +} + +QString Uf2Interface::getModuleEName(const QString& moduleXmlPath) +{ + QFile file(moduleXmlPath); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + return QString(); + } + + QXmlStreamReader xml(&file); + while (!xml.atEnd() && !xml.hasError()) { + QXmlStreamReader::TokenType token = xml.readNext(); + if (token == QXmlStreamReader::StartElement) { + QString elementName = xml.name().toString(); + if (elementName == "basic") { + QXmlStreamAttributes attrs = xml.attributes(); + if (attrs.hasAttribute("englishName")) { + return attrs.value("englishName").toString(); + } + } + } + } + + file.close(); + return QString(); +} + +bool Uf2Interface::shouldFilter(const QString& filePath, + const QStringList& completeNameList, + const QStringList& containNameList) +{ + QFileInfo fileInfo(filePath); + QString fileName = fileInfo.fileName(); + + if (completeNameList.contains(fileName)) { + LogManager::instance()->log(QString("过滤文件(文件名匹配): %1").arg(filePath)); + return true; + } + + for (const QString& name : containNameList) { + if (filePath.contains(name, Qt::CaseInsensitive)) { + LogManager::instance()->log(QString("过滤文件(路径包含): %1").arg(filePath)); + return true; + } + } + + LogManager::instance()->log(QString("保留文件: %1").arg(filePath)); + return false; +} + +QMap Uf2Interface::scanDir(const QString& dirPath, + const QString& ufAcct20ProjectDir, + const QString& uftDbSett, + const QMap& fileFilterDict) +{ + QMap resultMap; + QStringList completeNameList = fileFilterDict.value("completeNameList"); + QStringList containNameList = fileFilterDict.value("containNameList"); + + QMap moduleCodeMap; + moduleCodeMap["转融通"] = "ref"; + + auto scanModuleXml = [&](const QString& path) { + if (path.isEmpty()) return; + QDir dir(path); + QStringList filters; + filters << "module.xml"; + + QFileInfoList fileList = dir.entryInfoList(filters, QDir::Files); + for (const QFileInfo& fileInfo : fileList) { + QString filePath = fileInfo.absoluteFilePath(); + filePath.replace('\\', '/'); + + if (filePath.contains("/数据库/")) { + continue; + } + + QString modName = fileInfo.dir().dirName(); + QString modEName = getModuleEName(filePath); + moduleCodeMap[modName] = modEName; + } + + QDir subDirs(path); + QFileInfoList dirList = subDirs.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); + for (const QFileInfo& dirInfo : dirList) { + QDir subDir(dirInfo.absoluteFilePath()); + QFileInfoList subFileList = subDir.entryInfoList(filters, QDir::Files); + for (const QFileInfo& fileInfo : subFileList) { + QString filePath = fileInfo.absoluteFilePath(); + filePath.replace('\\', '/'); + + if (filePath.contains("/数据库/")) { + continue; + } + + QString modName = fileInfo.dir().dirName(); + QString modEName = getModuleEName(filePath); + moduleCodeMap[modName] = modEName; + } + } + }; + + scanModuleXml(dirPath); + scanModuleXml(ufAcct20ProjectDir); + scanModuleXml(uftDbSett); + + std::function scanInterfaceFilesRecursive; + scanInterfaceFilesRecursive = [&](const QString& path, const QString& serverType) { + if (path.isEmpty()) { + LogManager::instance()->log("路径为空,跳过"); + return; + } + QDir dir(path); + if (!dir.exists()) { + LogManager::instance()->log(QString("目录不存在: %1").arg(path)); + return; + } + QStringList filters; + filters << "*.*"; + + QFileInfoList fileList = dir.entryInfoList(filters, QDir::Files); + for (const QFileInfo& fileInfo : fileList) { + QString filePath = fileInfo.absoluteFilePath(); + filePath.replace('\\', '/'); + if (shouldFilter(filePath, completeNameList, containNameList)) { + continue; + } + + QString modName = fileInfo.dir().dirName(); + InterfaceInfo interfaceInfo = loadInterface(filePath); + interfaceInfo.moudle = modName; + interfaceInfo.moudleEName = moduleCodeMap.value(modName); + interfaceInfo.serverType = serverType; + + QString key = interfaceInfo.cname; + if (resultMap.contains(key)) { + QString existingPath = resultMap[key].path; + if (existingPath.contains("不用编译")) { + resultMap[key] = interfaceInfo; + } else if (!filePath.contains("不用编译")) { + LogManager::instance()->logWarning(QString("存在重复接口名: %1").arg(key)); + } + } else { + resultMap[key] = interfaceInfo; + } + } + + QFileInfoList dirList = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); + for (const QFileInfo& dirInfo : dirList) { + QString subDirPath = dirInfo.absoluteFilePath(); + subDirPath.replace('\\', '/'); + scanInterfaceFilesRecursive(subDirPath, serverType); + } + }; + + auto scanInterfaceFiles = [&](const QString& path, const QString& serverType) { + scanInterfaceFilesRecursive(path, serverType); + }; + + scanInterfaceFiles(dirPath, "trade"); + scanInterfaceFiles(ufAcct20ProjectDir, "acct"); + scanInterfaceFiles(uftDbSett, "dbsett"); + + LogManager::instance()->log(QString("扫描完成,共找到 %1 个接口").arg(resultMap.size())); + + return resultMap; +} diff --git a/src/metadataupdate/uf2interface.h b/src/metadataupdate/uf2interface.h new file mode 100644 index 0000000..a5eab6d --- /dev/null +++ b/src/metadataupdate/uf2interface.h @@ -0,0 +1,62 @@ +#ifndef UF2INTERFACE_H +#define UF2INTERFACE_H + +#include +#include +#include +#include + +struct FieldInfo { + QString name; + QString flag; + QString desc; + QString uuid; + QString paramType; + QString type; + QString cname; + QString hsType; +}; + +struct InterfaceInfo { + QString cname; + QString eName; + QString functionNo; + QString flag; + QString path; + QString code; + QString id; + QString sysStatus; + QString description; + QString moudle; + QString moudleEName; + QString serverType; + bool returnResultSet = false; + bool needTransMonitor = false; + bool checkLicence = false; + + QMap inputFields; + QMap outputFields; + QMap variableFields; + QMap internalFields; +}; + +class Uf2Interface : public QObject +{ + Q_OBJECT +public: + explicit Uf2Interface(QObject *parent = nullptr); + + InterfaceInfo loadInterface(const QString& filePath); + QMap scanDir(const QString& dirPath, + const QString& ufAcct20ProjectDir, + const QString& uftDbSett, + const QMap& fileFilterDict); + +private: + QString getModuleEName(const QString& moduleXmlPath); + bool shouldFilter(const QString& filePath, + const QStringList& completeNameList, + const QStringList& containNameList); +}; + +#endif // UF2INTERFACE_H \ No newline at end of file diff --git a/src/metadataupdate/uft3interface.cpp b/src/metadataupdate/uft3interface.cpp new file mode 100644 index 0000000..b49627f --- /dev/null +++ b/src/metadataupdate/uft3interface.cpp @@ -0,0 +1,240 @@ +#include "uft3interface.h" +#include "utils/logmanager.h" +#include "filedb.h" +#include +#include +#include +#include +#include + +Uft3Interface::Uft3Interface(QObject *parent) : QObject(parent) +{ +} + +InterfaceInfo Uft3Interface::loadInterface(const QString& filePath) +{ + InterfaceInfo result; + result.path = filePath; + + QString sFilePath = filePath; + sFilePath.replace('\\', '/'); + + QFileInfo fileInfo(sFilePath); + if (!fileInfo.exists()) { + LogManager::instance()->logError(QString("文件不存在: %1").arg(sFilePath)); + return result; + } + + QFile file(sFilePath); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + LogManager::instance()->logError(QString("无法打开文件: %1").arg(sFilePath)); + return result; + } + + QTextStream in(&file); + QString line = in.readLine(); + line = in.readLine(); + + if (!line.isEmpty()) { + int pos = line.indexOf("chineseName=\""); + if (pos != -1) { + pos += QString("chineseName=\"").length(); + int endPos = line.indexOf('"', pos); + if (endPos != -1) { + result.cname = line.mid(pos, endPos - pos).trimmed(); + } + } + + pos = line.indexOf("objectId=\""); + if (pos != -1) { + pos += QString("objectId=\"").length(); + int endPos = line.indexOf('"', pos); + if (endPos != -1) { + result.functionNo = line.mid(pos, endPos - pos).trimmed(); + } + } + + pos = line.indexOf("description=\""); + if (pos != -1) { + pos += QString("description=\"").length(); + int endPos = line.indexOf('"', pos); + if (endPos != -1) { + result.description = line.mid(pos, endPos - pos).trimmed(); + } + } + + pos = line.indexOf("interfaceFlag=\""); + if (pos != -1) { + pos += QString("interfaceFlag=\"").length(); + int endPos = line.indexOf('"', pos); + if (endPos != -1) { + result.flag = line.mid(pos, endPos - pos).trimmed(); + } + } + + pos = line.indexOf("id=\""); + if (pos != -1) { + pos += QString("id=\"").length(); + int endPos = line.indexOf('"', pos); + if (endPos != -1) { + result.id = line.mid(pos, endPos - pos).trimmed(); + } + } + + pos = line.indexOf("sysStatus=\""); + if (pos != -1) { + pos += QString("sysStatus=\"").length(); + int endPos = line.indexOf('"', pos); + if (endPos != -1) { + result.sysStatus = line.mid(pos, endPos - pos).trimmed(); + } + } + } + + result.eName = fileInfo.baseName(); + + file.seek(0); + QXmlStreamReader xml(&file); + + while (!xml.atEnd() && !xml.hasError()) { + QXmlStreamReader::TokenType token = xml.readNext(); + + if (token == QXmlStreamReader::StartElement) { + QString elementName = xml.name().toString(); + + if (elementName == "inputParameters") { + QXmlStreamAttributes attrs = xml.attributes(); + FieldInfo field; + field.name = attrs.value("id").toString(); + field.flag = attrs.value("flags").toString(); + field.desc = attrs.value("comments").toString(); + field.uuid = attrs.value("uuid").toString(); + result.inputFields[field.name] = field; + } + else if (elementName == "outputParameters") { + QXmlStreamAttributes attrs = xml.attributes(); + FieldInfo field; + field.name = attrs.value("id").toString(); + field.flag = attrs.value("flags").toString(); + field.desc = attrs.value("comments").toString(); + field.paramType = attrs.value("paramType").toString(); + field.uuid = attrs.value("uuid").toString(); + result.outputFields[field.name] = field; + + if (field.flag.contains("IO")) { + result.inputFields[field.name] = field; + } + } + else if (elementName == "internalParams") { + QXmlStreamAttributes attrs = xml.attributes(); + FieldInfo field; + field.name = attrs.value("id").toString(); + field.type = attrs.value("type").toString(); + field.desc = attrs.value("name").toString(); + field.paramType = attrs.value("paramType").toString(); + field.uuid = attrs.value("uuid").toString(); + result.internalFields[field.name] = field; + } + else if (elementName == "code") { + result.code = xml.readElementText(); + } + } + } + + file.close(); + + if (!result.functionNo.isEmpty() && !FileDB::instance()->uft3RealFunctionList.contains(result.functionNo)) { + FileDB::instance()->uft3RealFunctionList.append(result.functionNo); + } + + return result; +} + +bool Uft3Interface::shouldFilter(const QString& filePath, + const QString& dirPath, + const QStringList& completeNameList, + const QStringList& containNameList, + const QString& moduleGenerationCheck) +{ + QFileInfo fileInfo(filePath); + QString fileName = fileInfo.fileName(); + QString relPath = filePath.mid(dirPath.length()); + + QString suffix = relPath.mid(relPath.indexOf('.')); + if (!containNameList.contains(suffix)) { + return true; + } + + if (completeNameList.contains(fileName)) { + return true; + } + + if (moduleGenerationCheck == "1") { + if (filePath.contains("/cbp/") || filePath.contains("/ucbp/")) { + return true; + } + } + + return false; +} + +void Uft3Interface::scanDirRecursive(const QString& dirPath, + const QStringList& completeNameList, + const QStringList& containNameList, + const QString& moduleGenerationCheck, + QMap& resultMap, + QMap& transCodeMap) +{ + QDir dir(dirPath); + QStringList filters; + filters << "*.*"; + + QFileInfoList fileList = dir.entryInfoList(filters, QDir::Files); + for (const QFileInfo& fileInfo : fileList) { + QString filePath = fileInfo.absoluteFilePath(); + filePath.replace('\\', '/'); + + if (shouldFilter(filePath, dirPath, completeNameList, containNameList, moduleGenerationCheck)) { + continue; + } + + bool isTransCode = (filePath.contains("/cbptrans/") || + filePath.contains("/mgrcbptrans/") || + filePath.contains("/converttrans/") || + filePath.contains("/ses/")) && + !filePath.contains("/cbptrans/cbptranspub/"); + + QString modName = fileInfo.dir().dirName(); + InterfaceInfo interfaceInfo = loadInterface(filePath); + interfaceInfo.moudle = modName; + + if (isTransCode) { + transCodeMap[interfaceInfo.cname] = interfaceInfo; + continue; + } + + resultMap[interfaceInfo.cname] = interfaceInfo; + } + + QFileInfoList dirList = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); + for (const QFileInfo& dirInfo : dirList) { + scanDirRecursive(dirInfo.absoluteFilePath(), completeNameList, + containNameList, moduleGenerationCheck, resultMap, transCodeMap); + } +} + +QPair, QMap> +Uft3Interface::scanDir(const QString& dirPath, + const QMap& fileFilterDict, + const QString& moduleGenerationCheck) +{ + QMap resultMap; + QMap transCodeMap; + + QStringList completeNameList = fileFilterDict.value("completeNameList"); + QStringList containNameList = fileFilterDict.value("containNameList"); + + scanDirRecursive(dirPath, completeNameList, containNameList, moduleGenerationCheck, resultMap, transCodeMap); + + return qMakePair(resultMap, transCodeMap); +} diff --git a/src/metadataupdate/uft3interface.h b/src/metadataupdate/uft3interface.h new file mode 100644 index 0000000..b7bb69a --- /dev/null +++ b/src/metadataupdate/uft3interface.h @@ -0,0 +1,39 @@ +#ifndef UFT3INTERFACE_H +#define UFT3INTERFACE_H + +#include +#include +#include +#include +#include + +#include "uf2interface.h" + +class Uft3Interface : public QObject +{ + Q_OBJECT +public: + explicit Uft3Interface(QObject *parent = nullptr); + + InterfaceInfo loadInterface(const QString& filePath); + QPair, QMap> + scanDir(const QString& dirPath, + const QMap& fileFilterDict, + const QString& moduleGenerationCheck); + +private: + bool shouldFilter(const QString& filePath, + const QString& dirPath, + const QStringList& completeNameList, + const QStringList& containNameList, + const QString& moduleGenerationCheck); + + void scanDirRecursive(const QString& dirPath, + const QStringList& completeNameList, + const QStringList& containNameList, + const QString& moduleGenerationCheck, + QMap& resultMap, + QMap& transCodeMap); +}; + +#endif // UFT3INTERFACE_H \ No newline at end of file diff --git a/src/pages/metadatupdate/metadatupdatepage.cpp b/src/pages/metadatupdate/metadatupdatepage.cpp index 53f8af6..27086dd 100644 --- a/src/pages/metadatupdate/metadatupdatepage.cpp +++ b/src/pages/metadatupdate/metadatupdatepage.cpp @@ -4,6 +4,9 @@ #include #include #include +#include +#include +#include const int UPDATE_ITEM_SHOW_COLUMN_COUNT = 3; @@ -11,10 +14,15 @@ MetadataUpdatePage::MetadataUpdatePage(QWidget *parent) : ElaScrollPage(parent) { initUI(); + _processor = new MetadataProcessor(this); } MetadataUpdatePage::~MetadataUpdatePage() { + if (_workerThread && _workerThread->isRunning()) { + _workerThread->quit(); + _workerThread->wait(); + } } void MetadataUpdatePage::initUI() @@ -188,7 +196,12 @@ void MetadataUpdatePage::onUpdateUF20() return; } - QMessageBox::information(this, "提示", QString("UF20更新功能开发中,已选择: %1").arg(selectedItems.join(", "))); + _uf2UpdateBtn->setEnabled(false); + _uf2AllBtn->setEnabled(false); + _uf2CancelBtn->setEnabled(false); + _progressBar->setValue(0); + + updateUf2Interfaces(selectedItems); } void MetadataUpdatePage::onUFT3SelectAll() @@ -219,5 +232,121 @@ void MetadataUpdatePage::onUpdateUFT3() return; } - QMessageBox::information(this, "提示", QString("UFT30更新功能开发中,已选择: %1").arg(selectedItems.join(", "))); + _uft3UpdateBtn->setEnabled(false); + _uft3AllBtn->setEnabled(false); + _uft3CancelBtn->setEnabled(false); + _progressBar->setValue(0); + + updateUft3Interfaces(selectedItems); +} + +void MetadataUpdatePage::updateUf2Interfaces(const QStringList& items) +{ + QString basePath = QCoreApplication::applicationDirPath(); + + foreach (const QString& item, items) { + _processLabel->setText(QString("正在更新UF20 - %1").arg(item)); + _progressBar->setValue((items.indexOf(item) + 1) * 100 / items.size()); + + if (item == "标准字段") { + processUf2StdFields(basePath); + } else if (item == "数据类型") { + processUf2DataType(basePath); + } else if (item == "标准错误号") { + processUf2ErrNumber(basePath); + } else if (item == "接口数据") { + processUf2Interface(basePath); + } + } + + onUpdateFinished(true, "UF20更新完成"); +} + +void MetadataUpdatePage::updateUft3Interfaces(const QStringList& items) +{ + QString basePath = QCoreApplication::applicationDirPath(); + + foreach (const QString& item, items) { + _processLabel->setText(QString("正在更新UFT30 - %1").arg(item)); + _progressBar->setValue((items.indexOf(item) + 1) * 100 / items.size()); + + if (item == "标准字段") { + processUft3StdFields(basePath); + } else if (item == "数据类型") { + processUft3DataType(basePath); + } else if (item == "标准错误号") { + processUft3ErrNumber(basePath); + } else if (item == "接口数据") { + processUft3Interface(basePath); + } + } + + onUpdateFinished(true, "UFT30更新完成"); +} + +void MetadataUpdatePage::processUf2StdFields(const QString& basePath) +{ + qInfo() << "处理UF20标准字段"; +} + +void MetadataUpdatePage::processUf2DataType(const QString& basePath) +{ + qInfo() << "处理UF20数据类型"; +} + +void MetadataUpdatePage::processUf2ErrNumber(const QString& basePath) +{ + qInfo() << "处理UF20标准错误号"; +} + +void MetadataUpdatePage::processUf2Interface(const QString& basePath) +{ + qInfo() << "处理UF20接口数据"; + _processor->processUf2Interfaces(basePath); +} + +void MetadataUpdatePage::processUft3StdFields(const QString& basePath) +{ + qInfo() << "处理UFT30标准字段"; +} + +void MetadataUpdatePage::processUft3DataType(const QString& basePath) +{ + qInfo() << "处理UFT30数据类型"; +} + +void MetadataUpdatePage::processUft3ErrNumber(const QString& basePath) +{ + qInfo() << "处理UFT30标准错误号"; +} + +void MetadataUpdatePage::processUft3Interface(const QString& basePath) +{ + qInfo() << "处理UFT30接口数据"; + _processor->processUft3Interfaces(basePath); +} + +void MetadataUpdatePage::onUpdateProgress(int progress, const QString& message) +{ + _progressBar->setValue(progress); + _processLabel->setText(message); +} + +void MetadataUpdatePage::onUpdateFinished(bool success, const QString& message) +{ + _progressBar->setValue(success ? 100 : 0); + _processLabel->setText(message); + + _uf2UpdateBtn->setEnabled(true); + _uf2AllBtn->setEnabled(true); + _uf2CancelBtn->setEnabled(true); + _uft3UpdateBtn->setEnabled(true); + _uft3AllBtn->setEnabled(true); + _uft3CancelBtn->setEnabled(true); + + if (success) { + QMessageBox::information(this, "提示", message); + } else { + QMessageBox::warning(this, "提示", message); + } } diff --git a/src/pages/metadatupdate/metadatupdatepage.h b/src/pages/metadatupdate/metadatupdatepage.h index 04bae3e..1ce66d1 100644 --- a/src/pages/metadatupdate/metadatupdatepage.h +++ b/src/pages/metadatupdate/metadatupdatepage.h @@ -6,8 +6,10 @@ #include "ElaText.h" #include "ElaProgressBar.h" #include "ElaCheckBox.h" +#include "metadataupdate/metadataprocessor.h" #include #include +#include class MetadataUpdatePage : public ElaScrollPage { @@ -28,9 +30,25 @@ private slots: void onUFT3SelectNone(); void onUpdateUFT3(); +private slots: + void onUpdateProgress(int progress, const QString& message); + void onUpdateFinished(bool success, const QString& message); + private: void initUI(); void showUpdateItems(); + void updateUf2Interfaces(const QStringList& items); + void updateUft3Interfaces(const QStringList& items); + + void processUf2StdFields(const QString& basePath); + void processUf2DataType(const QString& basePath); + void processUf2ErrNumber(const QString& basePath); + void processUf2Interface(const QString& basePath); + + void processUft3StdFields(const QString& basePath); + void processUft3DataType(const QString& basePath); + void processUft3ErrNumber(const QString& basePath); + void processUft3Interface(const QString& basePath); QGridLayout* _updateGridLayout{nullptr}; QGridLayout* _updateUf2GridLayout{nullptr}; @@ -45,6 +63,9 @@ private: QList uft3CheckBoxes; QList uf20CheckBoxes; + + MetadataProcessor* _processor{nullptr}; + QThread* _workerThread{nullptr}; }; #endif \ No newline at end of file diff --git a/src/utils/logmanager.cpp b/src/utils/logmanager.cpp index fce4aab..57a916c 100644 --- a/src/utils/logmanager.cpp +++ b/src/utils/logmanager.cpp @@ -64,11 +64,11 @@ void LogManager::writeLog(const QString& level, const QString& message) } if (level == "ERROR") { - qCritical() << message; + qCritical().noquote() << message; } else if (level == "WARNING") { - qWarning() << message; + qWarning().noquote() << message; } else { - qDebug() << message; + qDebug().noquote() << message; } }