元数据页面实现更新UF20、UFT30接口数据

This commit is contained in:
taocong 2026-05-28 19:44:36 +08:00
parent 5f3a8cc8dd
commit b55596078d
13 changed files with 1238 additions and 5 deletions

View File

@ -16,6 +16,10 @@ SOURCES += main.cpp \
src/pages/help/helppage.cpp \ src/pages/help/helppage.cpp \
src/pages/settings/settingspage.cpp \ src/pages/settings/settingspage.cpp \
src/pages/metadatupdate/metadatupdatepage.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/datacache.cpp \
src/utils/uf2configreader.cpp \ src/utils/uf2configreader.cpp \
src/utils/uft3configreader.cpp \ src/utils/uft3configreader.cpp \
@ -31,6 +35,10 @@ HEADERS += src/mainwindow/mainwindow.h \
src/pages/help/helppage.h \ src/pages/help/helppage.h \
src/pages/settings/settingspage.h \ src/pages/settings/settingspage.h \
src/pages/metadatupdate/metadatupdatepage.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/datacache.h \
src/utils/uf2configreader.h \ src/utils/uf2configreader.h \
src/utils/uft3configreader.h \ src/utils/uft3configreader.h \

View File

@ -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;
}

View File

@ -0,0 +1,20 @@
#ifndef FILEDB_H
#define FILEDB_H
#include <QObject>
#include <QStringList>
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

View File

@ -0,0 +1,47 @@
#include "uf2interface.h"
#include "uft3interface.h"
#include "filedb.h"
#include <QCoreApplication>
#include <QCommandLineParser>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDebug>
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

View File

@ -0,0 +1,339 @@
#include "metadataprocessor.h"
#include "uf2interface.h"
#include "uft3interface.h"
#include "filedb.h"
#include "utils/logmanager.h"
#include <QFile>
#include <QFileInfo>
#include <QSettings>
#include <QDir>
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<QString, QStringList> 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<QString, InterfaceInfo> 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<QString, QStringList> 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<QString, InterfaceInfo> resultMap = result.first;
QMap<QString, InterfaceInfo> 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;
}

View File

@ -0,0 +1,33 @@
#ifndef METADATAPROCESSOR_H
#define METADATAPROCESSOR_H
#include <QObject>
#include <QString>
#include <QMap>
#include <QJsonDocument>
#include <QJsonObject>
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

View File

@ -0,0 +1,280 @@
#include "uf2interface.h"
#include "utils/logmanager.h"
#include <QFile>
#include <QFileInfo>
#include <QDebug>
#include <QDir>
#include <QStack>
#include <functional>
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<QString> 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<QString, InterfaceInfo> Uf2Interface::scanDir(const QString& dirPath,
const QString& ufAcct20ProjectDir,
const QString& uftDbSett,
const QMap<QString, QStringList>& fileFilterDict)
{
QMap<QString, InterfaceInfo> resultMap;
QStringList completeNameList = fileFilterDict.value("completeNameList");
QStringList containNameList = fileFilterDict.value("containNameList");
QMap<QString, QString> 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<void(const QString&, const QString&)> 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;
}

View File

@ -0,0 +1,62 @@
#ifndef UF2INTERFACE_H
#define UF2INTERFACE_H
#include <QObject>
#include <QString>
#include <QMap>
#include <QXmlStreamReader>
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<QString, FieldInfo> inputFields;
QMap<QString, FieldInfo> outputFields;
QMap<QString, FieldInfo> variableFields;
QMap<QString, FieldInfo> internalFields;
};
class Uf2Interface : public QObject
{
Q_OBJECT
public:
explicit Uf2Interface(QObject *parent = nullptr);
InterfaceInfo loadInterface(const QString& filePath);
QMap<QString, InterfaceInfo> scanDir(const QString& dirPath,
const QString& ufAcct20ProjectDir,
const QString& uftDbSett,
const QMap<QString, QStringList>& fileFilterDict);
private:
QString getModuleEName(const QString& moduleXmlPath);
bool shouldFilter(const QString& filePath,
const QStringList& completeNameList,
const QStringList& containNameList);
};
#endif // UF2INTERFACE_H

View File

@ -0,0 +1,240 @@
#include "uft3interface.h"
#include "utils/logmanager.h"
#include "filedb.h"
#include <QFile>
#include <QFileInfo>
#include <QDebug>
#include <QDir>
#include <QTextStream>
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<QString, InterfaceInfo>& resultMap,
QMap<QString, InterfaceInfo>& 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<QString, InterfaceInfo>, QMap<QString, InterfaceInfo>>
Uft3Interface::scanDir(const QString& dirPath,
const QMap<QString, QStringList>& fileFilterDict,
const QString& moduleGenerationCheck)
{
QMap<QString, InterfaceInfo> resultMap;
QMap<QString, InterfaceInfo> transCodeMap;
QStringList completeNameList = fileFilterDict.value("completeNameList");
QStringList containNameList = fileFilterDict.value("containNameList");
scanDirRecursive(dirPath, completeNameList, containNameList, moduleGenerationCheck, resultMap, transCodeMap);
return qMakePair(resultMap, transCodeMap);
}

View File

@ -0,0 +1,39 @@
#ifndef UFT3INTERFACE_H
#define UFT3INTERFACE_H
#include <QObject>
#include <QString>
#include <QMap>
#include <QXmlStreamReader>
#include <QPair>
#include "uf2interface.h"
class Uft3Interface : public QObject
{
Q_OBJECT
public:
explicit Uft3Interface(QObject *parent = nullptr);
InterfaceInfo loadInterface(const QString& filePath);
QPair<QMap<QString, InterfaceInfo>, QMap<QString, InterfaceInfo>>
scanDir(const QString& dirPath,
const QMap<QString, QStringList>& 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<QString, InterfaceInfo>& resultMap,
QMap<QString, InterfaceInfo>& transCodeMap);
};
#endif // UFT3INTERFACE_H

View File

@ -4,6 +4,9 @@
#include <QGridLayout> #include <QGridLayout>
#include <QMessageBox> #include <QMessageBox>
#include <QSpacerItem> #include <QSpacerItem>
#include <QCoreApplication>
#include <QDir>
#include <QTimer>
const int UPDATE_ITEM_SHOW_COLUMN_COUNT = 3; const int UPDATE_ITEM_SHOW_COLUMN_COUNT = 3;
@ -11,10 +14,15 @@ MetadataUpdatePage::MetadataUpdatePage(QWidget *parent)
: ElaScrollPage(parent) : ElaScrollPage(parent)
{ {
initUI(); initUI();
_processor = new MetadataProcessor(this);
} }
MetadataUpdatePage::~MetadataUpdatePage() MetadataUpdatePage::~MetadataUpdatePage()
{ {
if (_workerThread && _workerThread->isRunning()) {
_workerThread->quit();
_workerThread->wait();
}
} }
void MetadataUpdatePage::initUI() void MetadataUpdatePage::initUI()
@ -188,7 +196,12 @@ void MetadataUpdatePage::onUpdateUF20()
return; 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() void MetadataUpdatePage::onUFT3SelectAll()
@ -219,5 +232,121 @@ void MetadataUpdatePage::onUpdateUFT3()
return; 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);
}
} }

View File

@ -6,8 +6,10 @@
#include "ElaText.h" #include "ElaText.h"
#include "ElaProgressBar.h" #include "ElaProgressBar.h"
#include "ElaCheckBox.h" #include "ElaCheckBox.h"
#include "metadataupdate/metadataprocessor.h"
#include <QGridLayout> #include <QGridLayout>
#include <QMessageBox> #include <QMessageBox>
#include <QThread>
class MetadataUpdatePage : public ElaScrollPage class MetadataUpdatePage : public ElaScrollPage
{ {
@ -28,9 +30,25 @@ private slots:
void onUFT3SelectNone(); void onUFT3SelectNone();
void onUpdateUFT3(); void onUpdateUFT3();
private slots:
void onUpdateProgress(int progress, const QString& message);
void onUpdateFinished(bool success, const QString& message);
private: private:
void initUI(); void initUI();
void showUpdateItems(); 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* _updateGridLayout{nullptr};
QGridLayout* _updateUf2GridLayout{nullptr}; QGridLayout* _updateUf2GridLayout{nullptr};
@ -45,6 +63,9 @@ private:
QList<ElaCheckBox*> uft3CheckBoxes; QList<ElaCheckBox*> uft3CheckBoxes;
QList<ElaCheckBox*> uf20CheckBoxes; QList<ElaCheckBox*> uf20CheckBoxes;
MetadataProcessor* _processor{nullptr};
QThread* _workerThread{nullptr};
}; };
#endif #endif

View File

@ -64,11 +64,11 @@ void LogManager::writeLog(const QString& level, const QString& message)
} }
if (level == "ERROR") { if (level == "ERROR") {
qCritical() << message; qCritical().noquote() << message;
} else if (level == "WARNING") { } else if (level == "WARNING") {
qWarning() << message; qWarning().noquote() << message;
} else { } else {
qDebug() << message; qDebug().noquote() << message;
} }
} }