Compare commits

..

19 Commits
master ... main

Author SHA1 Message Date
taocong 6dfba8715d 修复元数据页面不显示问题 2026-06-12 10:12:40 +08:00
taocong dbb7059664 增加帮助页面网页代码功能,以及nginx部署 2026-06-10 17:17:07 +08:00
taocong edb693e5af 修复配置文件保存时编码异常问题,修改关于和帮助页面 2026-06-10 17:11:59 +08:00
taocong d891b4f583 帮助页面修改 2026-06-03 09:07:26 +08:00
taocong 5718503f26 增加转码功能函数配置修改自动刷新机制 2026-06-02 10:39:01 +08:00
taocong cc7fc51399 新增自定义控件,修复查询添加问题 2026-06-01 19:32:23 +08:00
taocong fad539e127 修复转码模块缺失问题 2026-06-01 14:50:04 +08:00
taocong 4cb44fc2fa 修复编译警告 2026-06-01 09:41:27 +08:00
taocong 273da28390 完成元数据更新功能 2026-06-01 09:25:20 +08:00
taocong 8ecf44db1a 修复UF20、UFT30接口数据更新数据缺失问题 2026-05-29 09:40:33 +08:00
taocong b55596078d 元数据页面实现更新UF20、UFT30接口数据 2026-05-28 19:44:36 +08:00
taocong 5f3a8cc8dd 元数据页面风格调整 2026-05-28 13:37:53 +08:00
taocong 3e05ecd9d2 页面控件替换,新增元数据查询页面(功能未实现) 2026-05-28 08:57:13 +08:00
taocong aa1bb42467 解决设置界面及保存配置后乱码问题 2026-05-27 09:40:44 +08:00
taocong 2af12b298c 新增功能查询页面,支持按名称和功能号查询 2026-05-26 16:13:51 +08:00
taocong c097120ca3 新增缓存数据库存储、转码进度显示 2026-05-26 14:33:03 +08:00
taocong fd38553be1 折叠按钮修改,转码页面优化 2026-05-26 09:59:17 +08:00
taocong 5bd09d58eb Merge branch 'master' 2026-05-25 10:20:43 +08:00
Ablert bb126cbeeb 添加 README.md
添加md

Signed-off-by: Ablert <15979130615@163.com>
2026-05-25 10:11:04 +08:00
133 changed files with 6246 additions and 520 deletions

8
.gitignore vendored
View File

@ -5,9 +5,17 @@
!python_bindings/**
!src/
!src/**
!help/
!help/**
!resources/
!resources/**
!*.bat
!*.rc
!*.prp
!*.cpp
!*.qrc
!*.h
!*.pro
!*.md
!.gitignore
!.gitkeep

24
ICON_GUIDE.md Normal file
View File

@ -0,0 +1,24 @@
# 图标设置说明
## 已完成配置
1. **应用程序窗口图标** - 已设置为 `resources/icons/转码工具.svg`
2. **资源文件** - 图标已添加到 `resources.qrc`
## Windows 可执行程序图标(可选)
如需设置 Windows 可执行文件的图标(任务栏、文件管理器显示的图标),需要:
### 方法 1使用在线工具转换
1. 将 `resources/images/转码工具.png` 转换为 `.ico` 格式
2. 推荐尺寸:包含 16x16, 32x32, 48x48, 256x256 等多种尺寸
3. 保存为 `app.ico` 并放在项目根目录
4. `app.rc` 已配置引用 `app.ico`
### 方法 2使用 ImageMagick 转换
```bash
magick convert 转码工具.png -define icon:auto-resize=256,128,96,64,48,32,16 app.ico
```
### 重新编译
设置好图标后重新编译项目即可。

0
README.md Normal file
View File

89
Uft30ChangeCode.pro Normal file
View File

@ -0,0 +1,89 @@
QT += core gui widgets sql
TARGET = Uft30ChangeCode
TEMPLATE = app
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += main.cpp \
src/mainwindow/mainwindow.cpp \
src/pythonrunner/PythonRunner.cpp \
src/pages/about/aboutdialog.cpp \
src/pages/batchconvert/batchconvertpage.cpp \
src/pages/functionsearch/functionsearchpage.cpp \
src/pages/functionsearch/uf20functionsearchpage.cpp \
src/pages/functionsearch/uft3functionsearchpage.cpp \
src/components/elasearchedit.cpp \
src/components/interdialog.cpp \
src/pages/help/helpdocpage.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/metadataupdate/uf2datatype.cpp \
src/metadataupdate/uf2stdfields.cpp \
src/metadataupdate/uf2errnumber.cpp \
src/metadataupdate/uft3datatype.cpp \
src/metadataupdate/uft3stdfields.cpp \
src/metadataupdate/uft3table.cpp \
src/utils/datacache.cpp \
src/utils/uf2configreader.cpp \
src/utils/uft3configreader.cpp \
src/utils/logmanager.cpp \
src/utils/configmanager.cpp \
src/utils/version.cpp
HEADERS += src/mainwindow/mainwindow.h \
src/pythonrunner/PythonRunner.h \
src/pages/about/aboutdialog.h \
src/pages/batchconvert/batchconvertpage.h \
src/pages/functionsearch/functionsearchpage.h \
src/pages/functionsearch/uf20functionsearchpage.h \
src/pages/functionsearch/uft3functionsearchpage.h \
src/components/elasearchedit.h \
src/components/interdialog.h \
src/pages/help/helpdocpage.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/metadataupdate/uf2datatype.h \
src/metadataupdate/uf2stdfields.h \
src/metadataupdate/uf2errnumber.h \
src/metadataupdate/uft3datatype.h \
src/metadataupdate/uft3stdfields.h \
src/metadataupdate/uft3table.h \
src/utils/datacache.h \
src/utils/uf2configreader.h \
src/utils/uft3configreader.h \
src/utils/logmanager.h \
src/utils/configmanager.h \
src/utils/version.h
RESOURCES += resources.qrc
CONFIG += c++17
CONFIG += debug_and_release
QMAKE_CXXFLAGS += -Wall -Wextra
QMAKE_LFLAGS += -fno-use-linker-plugin
INCLUDEPATH += src
INCLUDEPATH += 3rd/ElaWidgetTools/include
win32 {
LIBS += -L$$PWD/3rd/ElaWidgetTools/lib -lElaWidgetTools
LIBS += -ld3d11 -ldxgi
RC_FILE = app.rc
}
DESTDIR = $$PWD/bin
OBJECTS_DIR = $$PWD/build
MOC_DIR = $$PWD/build
RCC_DIR = $$PWD/build

2
app.rc
View File

@ -1 +1 @@
IDI_ICON1 ICON DISCARDABLE "app.ico"
IDI_ICON1 ICON DISCARDABLE "resources/images/ChangeCode.ico"

View File

@ -66,8 +66,8 @@ echo [OK] qmake done
echo.
REM Compile
echo [4/4] Compiling Debug version...
mingw32-make debug
echo [4/4] Compiling Release version...
mingw32-make release
if errorlevel 1 (
echo.
echo ERROR: Compilation failed

3
help/.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# 默认忽略的文件
/shelf/
/workspace.xml

1
help/.idea/.name Normal file
View File

@ -0,0 +1 @@
Uft30ChangeCodeHelp

6
help/.idea/misc.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

8
help/.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/help.iml" filepath="$PROJECT_DIR$/help.iml" />
</modules>
</component>
</project>

3
help/Writerside/.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# 默认忽略的文件
/shelf/
/workspace.xml

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/Writerside.iml" filepath="$PROJECT_DIR$/.idea/Writerside.iml" />
</modules>
</component>
</project>

6
help/Writerside/c.list Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE categories
SYSTEM "https://resources.jetbrains.com/writerside/1.0/categories.dtd">
<categories>
<category id="wrs" name="Writerside documentation" order="1"/>
</categories>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE buildprofiles SYSTEM "https://resources.jetbrains.com/writerside/1.0/build-profiles.dtd">
<buildprofiles xsi:noNamespaceSchemaLocation="https://resources.jetbrains.com/writerside/1.0/build-profiles.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<variables>
<custom-favicons>ChangeCode.png</custom-favicons>
</variables>
</buildprofiles>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE terms SYSTEM "https://resources.jetbrains.com/writerside/1.0/glossary.dtd">
<terms>
<term name="foo">
Description of what "foo" is.
</term>
</terms>

23
help/Writerside/hi.tree Normal file
View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE instance-profile
SYSTEM "https://resources.jetbrains.com/writerside/1.0/product-profile.dtd">
<instance-profile id="hi"
name="Uft30ChangeCode"
start-page="Uft30ChangeCode.md">
<toc-element topic="Uft30ChangeCode.md">
<toc-element topic="设置.md"/>
</toc-element>
<toc-element topic="功能转码.md">
<toc-element topic="业务转码.md"/>
</toc-element>
<toc-element topic="功能查询.md">
<toc-element topic="UFT3功能查询.md"/>
<toc-element topic="UF20功能查询.md"/>
</toc-element>
<toc-element topic="元数据更新.md"/>
<toc-element topic="更新记录.md">
<toc-element topic="update-1-0-0.md"/>
</toc-element>
<toc-element topic="下载.md"/>
</instance-profile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rules SYSTEM "https://resources.jetbrains.com/writerside/1.0/redirection-rules.dtd">
<rules>
<!-- format is as follows
<rule id="<unique id>">
<accepts>page.html</accepts>
</rule>
-->
<rule id="42b8a0d">
<description>Created after removal of "Empty MD Topic" from Uft30ChangeCode</description>
<accepts>Empty-MD-Topic.html</accepts>
</rule>
</rules>

View File

@ -0,0 +1,17 @@
# UF20功能查询
查询UFT3系统中的函数信息。
## 查询条件
从下拉框选择查询(功能名称、功能编号),输入框输入查询关键词,点击"Aa"切换精确/模糊匹配模式,点击放大镜图标或按回车执行查询
- 功能名称
<img src="功能名称查询.png" alt="功能名称查询"/>
- 功能编号
<img src="模糊查询uf20.png" alt="模糊查询uf20"/>
<img src="精准查询uf20.png" alt="精准查询uf20"/>
## 双击添加
双击选中行添加转码业务,只支持LS功能添加
<img src="双击添加.png" alt="双击添加"/>

View File

@ -0,0 +1,12 @@
# UFT3功能查询
查询UFT3系统中的函数信息。
## 查询条件
从下拉框选择查询(功能名称、功能编号),输入框输入查询关键词,点击"Aa"切换精确/模糊匹配模式,点击放大镜图标或按回车执行查询
- 功能名称
<img src="功能名称查询uft3.png" alt="功能名称查询uft3"/>
- 功能编号
<img src="模糊查询UFT3.png" alt="模糊查询UFT3"/>
<img src="精准查询uft3.png" alt="精准查询uft3"/>

View File

@ -0,0 +1,3 @@
# Uft30ChangeCode
提供UFT30元数据、UF20公共资源搜索功能支持业务转码

View File

@ -0,0 +1,11 @@
# 1.0.0
1.支持业务转码
2.支持代码uf20、uft3功能查找
3.支持帮助菜单和在线帮助文档
4.支持接口元数据更新
5.设置菜单UFT30项目环境路径、UF20项目环境路径、UF20账户环境路径、转码生成路径、支持弹窗选择目录。

View File

@ -0,0 +1,18 @@
# 下载
## 全量更新
下载全量包,解压即用。
> 1.0.0版本是基础版本,包含所需功能,如果是第一次下载,请选择全量包。
{style="note"}
## 增量更新
下载增量包,解压后替换原文件即可
> 1.0.0版本是基础版本如若要从旧版升级到1.0.0及以上版本可以选择增量版本下载并将旧版根目录下的uf2touft3和当前目录替换覆盖到新版根目录。
{style="note"}
## 下载
| 版本 | 更新日期 | 全量包 | 增量包 |
|------|------------|---------------------------------------------------------------------------------|-----|
| 1.0.0 | 2026-06-01 | [Uft30ChangeCode-1.0.0.zip](http://10.20.163.105:6045/download/uft3changecode/Uft30ChangeCode-1.0.0.zip) | |

View File

@ -0,0 +1,27 @@
# 业务转码
将UF20函数转换为UFT3函数格式的核心功能。
## 功能列表管理
点击"添加"按钮,输入函数名添加到转码列表
<img src="添加函数.png" alt="添加函数"/>
点击表格操作按钮可编辑函数名,如下:
<img src="编辑.png" alt="编辑"/>
选中行后点击"删除"移除函数、点击"清空"清空所有函数,如下:
<img src="删除.png" alt="删除"/>
## 配置文件同步
- 自动读取 uf2touft3/cust.json 配置
- 配置文件外部修改时自动刷新列表
## 转换操作
点击"开始转换"启动转换任务,转换过程中可查看进度条和状态信息,如下:
<img src="转码.png" alt="转码"/>
点击"停止转换"中止当前任务,如下:
<img src="停止转码.png" alt="停止转码"/>

View File

@ -0,0 +1,25 @@
# 元数据更新
更新UF20和UFT3系统的元数据配置。
## 项目配置
需要先配置UFT30项目路径和UF20项目路径。
在设置-首选项页面配置UFT30项目路径例如
``在设置-首选项页面配置UFT30项目路径例如``
<img src="UFT3项目环境路径.png" alt="UFT3项目环境路径"/>
在设置-首选项页面配置UF20项目路径例如
``E:\05.code\04.SVN\secu\dep1\hstrade20\trunk\Sources\DevCodes\经纪业务运营平台V21``
<img src="UF20项目环境路径.png" alt="UF20项目环境路径"/>
## UFT3元数据
在 元数据更新 页面,选择更新范围(标准字段、接口数据等)并点击更新UFT3按钮完成元数据更新。
<img src="UFT3元数据.png" alt="UFT3元数据"/>
**备注:接口数据更新比较久**
## 更新UF20元数据
在 元数据更新 页面,选择更新范围(标准字段、标准组件等)并点击更新UF2按钮完成公共资源更新
<img src="UF20元数据.png" alt="UF20元数据"/>
**备注:接口数据更新比较久**

View File

@ -0,0 +1,6 @@
# 功能查询
## 快速跳转
[UFT3功能查询](http://10.20.163.105:6045/uft3changecode/UFT3功能查询.html)
[UF20功能查询](http://10.20.163.105:6045/uft3changecode/UF20功能查询.html)

View File

@ -0,0 +1,32 @@
# 功能转码
提供UFT3业务转码功能将uf20代码转成UFT3代码
## 项目配置
在使用UFT3功能转码前需要先配置UFT30项目路径并更新UFT3、UF20元数据
1.配置项目路径
- UFT3项目环境路径
在设置-首选项页面配置UFT30项目路径转码使用例如
``E:\05.code\03.GIT\feature_ses``
<img src="UFT3项目环境路径.png" alt="UFT3项目环境路径"/>
- UF20项目环境路径
在设置-首选项页面UF20项目环境路径 转码需要读取相关的文件, 例如:
``E:\05.code\04.SVN\secu\dep1\hstrade20\trunk\Sources\DevCodes\经纪业务运营平台V21``
<img src="UF20项目环境路径.png" alt="UF20项目环境路径"/>
- UF20账户环境路径
在设置-首选项页面配置UF20账户环境路径 转码需要读取账户相关的文件,例如:
``E:\05.code\04.SVN\secu\dep1\hstrade20\trunk\Sources\DevCodes_Acct1\客户账户管理系统V22``
<img src="UF20账户环境路径.png" alt="UF20账户环境路径"/>
- 转码生成路径
在设置-首选项页面,配置转码生成路径, 用于存放生成的转码文件, 例如:
``F:\07.tools\01.hstools\Uft30ChangeCode\bin\uf2touft3\change_code``
<img src="转码生成路径.png" alt="转码生成路径"/>
## 快速跳转
[业务转码](http://10.20.163.105:6045/uft3changecode/业务转码.html)

View File

@ -0,0 +1,3 @@
# 更新记录
Start typing here...

View File

@ -0,0 +1,27 @@
# 设置
## UFT3项目环境路径
在设置-首选项页面配置UFT30项目路径转码使用例如
``E:\05.code\03.GIT\feature_ses``
## UF20项目环境路径 {id="uf20_1"}
在设置-首选项页面UF20项目环境路径 转码需要读取相关的文件, 例如:
``E:\05.code\04.SVN\secu\dep1\hstrade20\trunk\Sources\DevCodes\经纪业务运营平台V21``
## UF20账户环境路径
在设置-首选项页面配置UF20账户环境路径 转码需要读取账户相关的文件,例如:
``E:\05.code\04.SVN\secu\dep1\hstrade20\trunk\Sources\DevCodes_Acct1\客户账户管理系统V22``
## 转码生成路径
在设置-首选项页面,配置转码生成路径, 用于存放生成的转码文件, 例如:
``F:\07.tools\01.hstools\Uft30ChangeCode\bin\uf2touft3\change_code``
## 主题切换
包含日间模式和夜间模式。

5
help/Writerside/v.list Normal file
View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE vars SYSTEM "https://resources.jetbrains.com/writerside/1.0/vars.dtd">
<vars>
<var name="product" value="Writerside"/>
</vars>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ihp SYSTEM "https://resources.jetbrains.com/writerside/1.0/ihp.dtd">
<ihp version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://resources.jetbrains.com/writerside/1.0/writerside-cfg.xsd">
<topics dir="topics"/>
<images dir="images" web-path="images"/>
<categories src="c.list"/>
<vars src="v.list"/>
<instance src="hi.tree"/>
</ihp>

10
help/nginx/help.conf Normal file
View File

@ -0,0 +1,10 @@
server {
listen 6045;
server_name _;
location /uft3changecode/ {
alias /home/taoc/uft30help/uft3changecode/;
index index.html;
try_files $uri $uri/ /uft3changecode/index.html;
}
}

35
help/nginx/nginx.conf Normal file
View File

@ -0,0 +1,35 @@
worker_processes 1;
pid /home/taoc/nginx/logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include /home/taoc/nginx/conf/mime.types;
default_type application/octet-stream;
access_log /home/taoc/nginx/logs/help_access.log;
error_log /home/taoc/nginx/logs/help_error.log;
sendfile on;
keepalive_timeout 65;
server {
listen 6045;
server_name _;
root /home/taoc/uft30help/html/;
index index.html index.htm;
location /uft3changecode/ {
index index.html index.htm;
try_files $uri $uri/ /uft3changecode/index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}

View File

@ -0,0 +1,89 @@
#!/bin/bash
echo "=== Force Restart Help Documentation Server ==="
echo ""
echo "1. Killing all nginx processes..."
pkill -f nginx 2>/dev/null || true
sleep 2
echo "2. Checking for remaining nginx processes..."
if pgrep nginx > /dev/null; then
echo " Force killing remaining nginx processes..."
pkill -9 nginx 2>/dev/null || true
sleep 1
fi
echo "3. Checking port 6045..."
lsof -i :6045 2>/dev/null || echo " Port 6045 is free"
echo ""
echo "4. Starting fresh nginx instance..."
NGINX_BIN="/home/taoc/nginx/sbin/nginx"
HELP_DOCS_DIR="/home/taoc/uft30help/"
CONF_FILE="$HELP_DOCS_DIR/workspace/nginx.conf"
if [ ! -f "$CONF_FILE" ]; then
echo " Copying nginx configuration..."
cp "$(dirname "$0")/nginx.conf" "$CONF_FILE"
fi
if [ ! -f "$HELP_DOCS_DIR/workspace/help.conf" ]; then
echo " Copying server configuration..."
cp "$(dirname "$0")/help.conf" "$HELP_DOCS_DIR/workspace/help.conf"
fi
if [ ! -f "$HELP_DOCS_DIR/uft3changecode/index.html" ]; then
echo " Creating default index.html..."
cat > "$HELP_DOCS_DIR/uft3changecode/index.html" << 'EOF'
<!DOCTYPE html>
<html>
<head>
<title>UFT30ChangeCode Help</title>
<style>
body { font-family: Arial, sans-serif; text-align: center; padding: 50px; background: #f5f5f5; }
.container { background: white; padding: 40px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); display: inline-block; }
.logo { font-size: 64px; margin-bottom: 20px; }
h1 { color: #667eea; margin: 0; }
.subtitle { color: #666; margin-top: 10px; }
.path { background: #f0f0f0; padding: 10px 20px; border-radius: 5px; margin-top: 20px; font-family: monospace; }
</style>
</head>
<body>
<div class="container">
<div class="logo">📖</div>
<h1>UFT30ChangeCode Help</h1>
<p class="subtitle">Help Documentation Server</p>
<div class="path">Path: /uft3changecode/</div>
</div>
</body>
</html>
EOF
fi
echo "5. Testing configuration..."
"$NGINX_BIN" -t -c "$CONF_FILE"
echo "6. Starting nginx..."
"$NGINX_BIN" -c "$CONF_FILE"
sleep 2
echo ""
echo "=== Server Status ==="
if pgrep nginx > /dev/null; then
SERVER_IP=$(ip addr show | grep inet | grep -v '127.0.0.1' | grep -v '::1' | head -1 | awk '{print $2}' | cut -d'/' -f1)
echo "✅ Server started successfully!"
echo ""
echo "Access URLs:"
echo " Local: http://localhost:6045/uft3changecode/"
if [ -n "$SERVER_IP" ]; then
echo " Remote: http://$SERVER_IP:6045/uft3changecode/"
fi
echo ""
echo "Verify with:"
echo " curl http://localhost:6045/uft3changecode/"
else
echo "❌ Failed to start server"
echo "Check error log: /home/taoc/uft30help/workspace/logs/help_error.log"
fi

56
help/nginx/start.sh Normal file
View File

@ -0,0 +1,56 @@
#!/bin/bash
NGINX_BIN="/home/taoc/nginx/sbin/nginx"
CONF_DIR="/home/taoc/uft30help/workspace"
HTML_DIR="/home/taoc/uft30help/html/uft3changecode"
CONF_FILE="$CONF_DIR/nginx.conf"
echo "=== Starting Help Documentation Server (Port 6045) ==="
echo ""
echo "1. Checking directories..."
if [ ! -d "$CONF_DIR" ]; then
mkdir -p "$CONF_DIR"
echo " Created config dir: $CONF_DIR"
else
echo " Config dir exists: $CONF_DIR"
fi
if [ ! -d "$HTML_DIR" ]; then
mkdir -p "$HTML_DIR"
echo " Created HTML dir: $HTML_DIR"
else
echo " HTML dir exists: $HTML_DIR"
fi
echo ""
echo "2. Killing all nginx processes..."
pkill -f nginx 2>/dev/null || true
sleep 2
pkill -9 nginx 2>/dev/null || true
sleep 1
echo " Done"
echo ""
echo "3. Starting nginx..."
"$NGINX_BIN" -c "$CONF_FILE"
sleep 2
echo ""
echo "4. Testing..."
echo ""
echo "=== Server Status ==="
if pgrep nginx > /dev/null; then
SERVER_IP=$(ip addr show | grep inet | grep -v '127.0.0.1' | grep -v '::1' | head -1 | awk '{print $2}' | cut -d'/' -f1)
echo "✅ Server running!"
echo ""
echo "=== Access URLs ==="
echo " Local: http://localhost:6045/uft3changecode/"
if [ -n "$SERVER_IP" ]; then
echo " Remote: http://$SERVER_IP:6045/uft3changecode/"
fi
else
echo "❌ Server not running"
echo "Error log:"
tail -20 /home/taoc/uft30help/workspace/logs/help_error.log
fi

10
help/nginx/status.sh Normal file
View File

@ -0,0 +1,10 @@
#!/bin/bash
echo "Checking Help Documentation Server status..."
if pgrep nginx &> /dev/null; then
echo "✅ Help Documentation Server is running"
echo "📄 Access URL: http://localhost:8080"
else
echo "❌ Help Documentation Server is not running"
fi

19
help/nginx/stop.sh Normal file
View File

@ -0,0 +1,19 @@
#!/bin/bash
NGINX_DIR="/home/taoc/nginx"
NGINX_BIN="$NGINX_DIR/sbin/nginx"
echo "Stopping Help Documentation Server..."
if [ ! -f "$NGINX_BIN" ]; then
echo "Error: nginx binary not found at $NGINX_BIN"
exit 1
fi
"$NGINX_BIN" -s stop
if [ $? -eq 0 ]; then
echo "✅ Help Documentation Server stopped successfully"
else
echo "❌ Failed to stop nginx"
exit 1
fi

View File

@ -1,12 +1,20 @@
#include "src/mainwindow/mainwindow.h"
#include "ElaApplication.h"
#include "src/utils/configmanager.h"
#include <QApplication>
#include <QIcon>
#include <QCoreApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setWindowIcon(QIcon(":resources/images/ChangeCode.png"));
eApp->init();
QString basePath = QCoreApplication::applicationDirPath();
ConfigManager::instance()->loadConfig(basePath);
MainWindow w;
w.show();
w.showMaximized();
return a.exec();
}

View File

@ -1,4 +1,11 @@
<RCC>
<qresource prefix="/">
<file>resources/images/ChangeCode.png</file>
<file>resources/images/bianji.png</file>
<file>resources/images/zhedie_left.png</file>
<file>resources/images/zhedie_right.png</file>
<file>resources/images/max.png</file>
<file>resources/images/min.png</file>
<file>resources/images/update.png</file>
</qresource>
</RCC>

17
resources/README.md Normal file
View File

@ -0,0 +1,17 @@
# 资源目录
此目录用于存放项目使用的图标、图片等资源文件。
## 目录结构
```
resources/
├── icons/ # 图标文件
└── images/ # 图片文件
```
## 添加新资源
1. 将资源文件放入对应目录
2. 更新 resources.qrc 文件添加资源引用
3. 重新编译项目

164
resources/help/help.md Normal file
View File

@ -0,0 +1,164 @@
# 使用帮助
## 概述
欢迎使用 UFT30 Change Code 工具这是一款强大的编码转换工具支持批量转码和非LS格式转换。
### 功能导航
```
UFT30 Change Code
├── 📁 功能转码
│ └── 业务转码
├── 📁 功能查询
│ ├── UF20功能查询
│ └── UFT3功能查询
├── 元数据更新
├── 设置
├── 关于
└── 使用技巧
```
点击左侧导航栏的功能项,查看详细的使用说明。
## 功能转码
### 业务转码
将UF20函数转换为UFT3函数格式的核心功能。
#### 功能列表管理
- 点击"添加"按钮,输入函数名添加到转码列表
- 双击表格行可编辑函数名
- 选中行后点击"删除"移除函数
- 点击"清空"清空所有函数
#### 配置文件同步
- 自动读取 uf2touft3/cust.json 配置
- 配置文件外部修改时自动刷新列表
#### 转换操作
- 点击"开始转换"启动转换任务
- 转换过程中可查看进度条和状态信息
- 点击"停止转换"中止当前任务
## 功能查询
### UF20功能查询
查询UF20系统中的函数信息。
#### 查询条件
- 从下拉框选择查询字段:功能名称、英文名称、功能编号
- 输入框输入查询关键词
- 点击"Aa"切换精确/模糊匹配模式
- 点击放大镜图标或按回车执行查询
#### 结果操作
- 双击查询结果可直接添加到转码列表
- 结果表格显示:功能名称、英文名称、功能编号
### UFT3功能查询
查询UFT3系统中的函数信息。
#### 查询条件
- 从下拉框选择查询字段:功能名称、英文名称、功能编号
- 输入框输入查询关键词
- 点击"Aa"切换精确/模糊匹配模式
- 点击放大镜图标或按回车执行查询
#### 结果显示
- 结果表格显示:功能名称、英文名称、功能编号
## 元数据更新
更新UF20和UFT3系统的元数据配置。
### UF20配置更新
- 勾选需要更新的UF20接口项
- 点击"全选"选中所有UF20项
- 点击"取消"清除UF20选择
- 点击"更新UF20"执行更新
### UFT3配置更新
- 勾选需要更新的UFT3接口项
- 点击"全选"选中所有UFT3项
- 点击"取消"清除UFT3选择
- 点击"更新UFT3"执行更新
### 更新内容
- UF20: 接口、标准字段、数据类型、错误编号
- UFT3: 接口、标准字段、数据类型、表结构
## 设置
配置工具的运行参数和选项。
### 路径配置
- 设置Python脚本路径
- 配置转换工具路径
- 设置配置文件目录
### 显示设置
- 调整界面主题
- 设置字体大小
- 配置语言选项
### 高级设置
- 设置自动保存间隔
- 配置日志级别
- 设置最大并发任务数
## 关于
### UFT30 Change Code
一款强大的编码转换工具支持批量转码和非LS格式转换。
#### 基本信息
- **版本**: 1.0.0
- **作者**: UFT30 Team
- **版权**: Copyright © 2024
- **联系方式**: support@uft30.com
#### 功能特性
- 支持UF20到UFT3函数格式转换
- 批量转换处理
- 非LS格式转换支持
- 功能查询与快速添加
- 元数据自动更新
## 使用技巧
### 高效使用技巧
- 在功能查询中找到需要转换的函数,双击可快速添加到转码列表
- 精确匹配适合已知完整函数名的查询
- 模糊匹配可以使用部分关键词查找
- 配置文件可以手动编辑,工具会自动检测变化
- 批量转换前建议先进行元数据更新
- 使用Ctrl+F快速搜索帮助内容
### 注意事项
- 首次使用前请先执行"元数据更新"加载最新配置
- 转换前建议备份重要文件
- 确保 uf2touft3/uf2touft3.exe 存在且可执行
- 配置文件 uf2touft3/cust.json 会自动同步转码列表
- 大文件转换可能需要较长时间,请耐心等待

18
resources/help/tips.md Normal file
View File

@ -0,0 +1,18 @@
# 💡 使用技巧
## 高效使用技巧
- 在功能查询中找到需要转换的函数,双击可快速添加到转码列表
- 精确匹配适合已知完整函数名的查询
- 模糊匹配可以使用部分关键词查找
- 配置文件可以手动编辑,工具会自动检测变化
- 批量转换前建议先进行元数据更新
- 使用Ctrl+F快速搜索帮助内容
## 注意事项
- 首次使用前请先执行"元数据更新"加载最新配置
- 转换前建议备份重要文件
- 确保 uf2touft3/uf2touft3.exe 存在且可执行
- 配置文件 uf2touft3/cust.json 会自动同步转码列表
- 大文件转换可能需要较长时间,请耐心等待

1
resources/icons/.gitkeep Normal file
View File

@ -0,0 +1 @@
# 此文件用于保持icons目录在Git仓库中

View File

@ -0,0 +1 @@
# 此文件用于保持images目录在Git仓库中

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

BIN
resources/images/bianji.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
resources/images/chaxun.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

BIN
resources/images/delect.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

BIN
resources/images/max.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
resources/images/min.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
resources/images/update.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -0,0 +1,116 @@
#include "elasearchedit.h"
#include <QHBoxLayout>
#include "ElaIcon.h"
ElaSearchEdit::ElaSearchEdit(QWidget* parent)
: QWidget(parent), m_exactMatch(false)
{
initUI();
}
ElaSearchEdit::~ElaSearchEdit()
{
}
void ElaSearchEdit::initUI()
{
QHBoxLayout* mainLayout = new QHBoxLayout(this);
mainLayout->setSpacing(0);
mainLayout->setContentsMargins(0, 0, 0, 0);
m_lineEdit = new ElaLineEdit(this);
m_lineEdit->setFixedHeight(35);
m_lineEdit->setPlaceholderText("输入查询内容");
m_lineEdit->setIsClearButtonEnable(false);
QHBoxLayout* inputLayout = new QHBoxLayout(m_lineEdit);
inputLayout->setContentsMargins(0, 0, 4, 0);
inputLayout->addStretch();
m_exactMatchBtn = addToolButton(m_lineEdit, ElaIconType::FontCase, "区分大小写", QSize(26, 26), true, false);
inputLayout->addWidget(m_exactMatchBtn);
resetInputMargin();
mainLayout->addWidget(m_lineEdit);
m_searchBtn = addToolButton(this, ElaIconType::MagnifyingGlass, "搜索", QSize(35, 35), false, false);
mainLayout->addWidget(m_searchBtn);
connectSignals();
}
void ElaSearchEdit::connectSignals()
{
connect(m_lineEdit, &ElaLineEdit::textChanged, this, &ElaSearchEdit::textChanged);
connect(m_lineEdit, &ElaLineEdit::returnPressed, this, &ElaSearchEdit::returnPressed);
connect(m_searchBtn, &ElaToolButton::clicked, this, &ElaSearchEdit::searchClicked);
connect(m_exactMatchBtn, &ElaToolButton::clicked, this, [this](bool checked) {
m_exactMatch = checked;
emit exactMatchChanged(checked);
});
}
void ElaSearchEdit::resetInputMargin()
{
m_lineEdit->setTextMargins(0, 0, 30, 0);
}
ElaToolButton* ElaSearchEdit::addToolButton(QWidget* parent, ElaIconType::IconName icon, const QString& tooltip, const QSize& size, bool checkable, bool checked)
{
ElaToolButton* btn = new ElaToolButton(parent);
btn->setElaIcon(icon);
btn->setFixedSize(size);
btn->setToolTip(tooltip);
btn->setCheckable(checkable);
btn->setChecked(checked);
btn->setCursor(Qt::PointingHandCursor);
return btn;
}
QString ElaSearchEdit::text() const
{
return m_lineEdit->text();
}
void ElaSearchEdit::setText(const QString& text)
{
m_lineEdit->setText(text);
}
void ElaSearchEdit::setPlaceholderText(const QString& placeholderText)
{
m_lineEdit->setPlaceholderText(placeholderText);
}
void ElaSearchEdit::setFixedSize(const QSize& size)
{
m_lineEdit->setFixedSize(size.width() - 35, size.height());
m_searchBtn->setFixedSize(35, size.height());
QWidget::setFixedSize(size);
}
void ElaSearchEdit::setFixedSize(int w, int h)
{
m_lineEdit->setFixedSize(w - 35, h);
m_searchBtn->setFixedSize(35, h);
QWidget::setFixedSize(w, h);
}
void ElaSearchEdit::setFixedHeight(int h)
{
m_lineEdit->setFixedHeight(h);
m_searchBtn->setFixedSize(35, h);
QWidget::setFixedHeight(h);
}
bool ElaSearchEdit::isExactMatch() const
{
return m_exactMatch;
}
void ElaSearchEdit::setExactMatch(bool exact)
{
m_exactMatch = exact;
m_exactMatchBtn->setChecked(exact);
}

View File

@ -0,0 +1,46 @@
#ifndef ELASEARCHEDIT_H
#define ELASEARCHEDIT_H
#include <QWidget>
#include <QHBoxLayout>
#include <QList>
#include "ElaLineEdit.h"
#include "ElaToolButton.h"
class ElaSearchEdit : public QWidget
{
Q_OBJECT
public:
explicit ElaSearchEdit(QWidget* parent = nullptr);
~ElaSearchEdit() override;
QString text() const;
void setText(const QString& text);
void setPlaceholderText(const QString& placeholderText);
void setFixedSize(const QSize& size);
void setFixedSize(int w, int h);
void setFixedHeight(int h);
bool isExactMatch() const;
void setExactMatch(bool exact);
signals:
void textChanged(const QString& text);
void returnPressed();
void exactMatchChanged(bool exact);
void searchClicked();
private:
void initUI();
void connectSignals();
void resetInputMargin();
ElaToolButton* addToolButton(QWidget* parent, ElaIconType::IconName icon, const QString& tooltip, const QSize& size, bool checkable = false, bool checked = false);
ElaLineEdit* m_lineEdit;
ElaToolButton* m_searchBtn;
ElaToolButton* m_exactMatchBtn;
bool m_exactMatch;
};
#endif // ELASEARCHEDIT_H

View File

@ -0,0 +1,116 @@
#include "interdialog.h"
#include "ElaText.h"
#include "ElaPushButton.h"
#include <QSpacerItem>
InterDialog::InterDialog(QWidget* parent) : ElaDialog(parent)
{
this->setIsFixedSize(true);
this->setWindowModality(Qt::ApplicationModal);
this->setWindowButtonFlags(ElaAppBarType::CloseButtonHint);
this->setAppBarHeight(30);
_mainLayout = new QVBoxLayout(this);
_mainLayout->setContentsMargins(10, 10, 10, 10);
_centralWidget = new QWidget(this);
auto* centralVLayout = new QVBoxLayout(_centralWidget);
centralVLayout->setContentsMargins(0, 0, 0, 0);
_messageLabel = new ElaText("这是消息", _centralWidget);
_messageLabel->setIsWrapAnywhere(true);
centralVLayout->addWidget(_messageLabel);
_buttonWidget = new QWidget(this);
_btnLayout = new QHBoxLayout(_buttonWidget);
_btnLayout->setContentsMargins(0, 0, 0, 0);
_btnLayout->addItem(new QSpacerItem(5, 5, QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Minimum));
auto *defaultButton = new QPushButton(_buttonWidget);
defaultButton->setDefault(true);
defaultButton->hide();
_okButton = new ElaPushButton("确认", _buttonWidget);
connect(_okButton, &ElaPushButton::clicked, this, [=]
{
emit okButtonClicked();
accept();
});
_okButton->setLightDefaultColor(ElaThemeColor(ElaThemeType::Light, PrimaryNormal));
_okButton->setLightHoverColor(ElaThemeColor(ElaThemeType::Light, PrimaryHover));
_okButton->setLightPressColor(ElaThemeColor(ElaThemeType::Light, PrimaryPress));
_okButton->setLightTextColor(ElaThemeColor(ElaThemeType::Dark, BasicText));
_okButton->setDarkDefaultColor(ElaThemeColor(ElaThemeType::Dark, PrimaryNormal));
_okButton->setDarkHoverColor(ElaThemeColor(ElaThemeType::Dark, PrimaryHover));
_okButton->setDarkPressColor(ElaThemeColor(ElaThemeType::Dark, PrimaryPress));
_okButton->setDarkTextColor(ElaThemeColor(ElaThemeType::Light, BasicText));
_okButton->setMinimumSize(0, 0);
_okButton->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
_okButton->setFixedHeight(38);
_btnLayout->addWidget(_okButton);
_cancelButton = new ElaPushButton("取消", _buttonWidget);
connect(_cancelButton, &ElaPushButton::clicked, this, [=]
{
emit cancelButtonClicked();
reject();
});
_cancelButton->setMinimumSize(0, 0);
_cancelButton->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
_cancelButton->setFixedHeight(38);
_btnLayout->addWidget(_cancelButton);
_mainLayout->addWidget(_centralWidget);
_mainLayout->addWidget(_buttonWidget);
setFocus();
}
InterDialog::~InterDialog() = default;
void InterDialog::setMessage(const QString& message)
{
if (_messageLabel)
{
_messageLabel->setText(message);
}
}
void InterDialog::setCentralWidget(QWidget* centralWidget)
{
_mainLayout->removeWidget(_centralWidget);
delete _messageLabel;
_messageLabel = nullptr;
delete _centralWidget;
_centralWidget = centralWidget;
QSizePolicy sizePolicy(QSizePolicy::Policy::Preferred, QSizePolicy::Policy::Expanding);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(centralWidget->sizePolicy().hasHeightForWidth());
centralWidget->setSizePolicy(sizePolicy);
_mainLayout->insertWidget(0, _centralWidget);
}
void InterDialog::setStandardButtons(const QDialogButtonBox::StandardButtons buttons) const
{
if (buttons.testFlag(QDialogButtonBox::NoButton))
{
_buttonWidget->setVisible(false);
}
else
{
_okButton->setVisible(buttons.testFlag(QDialogButtonBox::StandardButton::Ok));
_cancelButton->setVisible(buttons.testFlag(QDialogButtonBox::StandardButton::Cancel));
}
}
void InterDialog::addFirstButton(QPushButton* button) const
{
_btnLayout->insertWidget(1, button);
}
void InterDialog::addLastButton(QPushButton* button) const
{
_btnLayout->addWidget(button);
}

View File

@ -0,0 +1,68 @@
#ifndef METASEARCH_INTERDIALOG_H
#define METASEARCH_INTERDIALOG_H
#include "ElaDialog.h"
#include "ElaTheme.h"
#include "ElaText.h"
#include "ElaPushButton.h"
#include <QDialogButtonBox>
#include <QVBoxLayout>
#include <QHBoxLayout>
/**
*
*/
class InterDialog : public ElaDialog
{
Q_OBJECT
public:
explicit InterDialog(QWidget* parent = nullptr);
~InterDialog() override;
// 设置消息
virtual void setMessage(const QString& message);
// 设置中心区域
void setCentralWidget(QWidget* centralWidget);
// 设置按钮
void setStandardButtons(QDialogButtonBox::StandardButtons buttons) const;
// 头部添加按钮
void addFirstButton(QPushButton* button) const;
// 尾部添加按钮
void addLastButton(QPushButton* button) const;
signals:
void okButtonClicked();
void cancelButtonClicked();
protected:
// 主题
ElaThemeType::ThemeMode _themeMode;
// 主布局
QVBoxLayout* _mainLayout{nullptr};
// 中心区域
QWidget* _centralWidget{nullptr};
// 中心区域文本
ElaText* _messageLabel{nullptr};
// 按钮区域
QWidget* _buttonWidget{nullptr};
// 按钮区域布局
QHBoxLayout* _btnLayout{nullptr};
// 确认按钮
ElaPushButton* _okButton{nullptr};
// 取消按钮
ElaPushButton* _cancelButton{nullptr};
};
#endif //METASEARCH_INTERDIALOG_H

View File

@ -2,6 +2,10 @@
#include "ElaIcon.h"
#include "ElaText.h"
#include "ElaTheme.h"
#include "ElaToolButton.h"
#include "utils/uf2configreader.h"
#include "utils/uft3configreader.h"
#include "utils/logmanager.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
@ -16,42 +20,82 @@
#include <QFileInfo>
#include <QCoreApplication>
#include <QDir>
#include <QTimer>
#include <QApplication>
#include <QDesktopServices>
#include <QUrl>
MainWindow::MainWindow(QWidget *parent)
: ElaWindow(parent)
, m_pythonRunner(new PythonRunner(this))
, m_iconsSet(false)
, m_navigationButton(nullptr)
, m_isNavigationExpanded(true)
{
initWindow();
initContent();
// 获取应用程序目录
LogManager::instance()->initLogFile();
LogManager::instance()->logInfo("应用程序启动");
QString appDir = QCoreApplication::applicationDirPath();
// 配置 Python 运行器 - 只使用打包好的 exe路径是 uf2touft3/uf2touft3.exe
loadConfigCache();
m_pythonRunner->setRunMode(PythonRunner::UsePackagedExe);
// 设置打包好的可执行文件路径和工作目录
QString exePath = appDir + "/uf2touft3/uf2touft3.exe";
QString workDir = appDir + "/uf2touft3";
m_pythonRunner->setPackagedExePath(exePath);
m_pythonRunner->setWorkingDirectory(workDir);
// 检查 exe 是否存在
QFileInfo exeInfo(exePath);
if (!exeInfo.exists() || !exeInfo.isFile()) {
m_batchLogEdit->append("⚠️ 警告:未找到 uf2touft3/uf2touft3.exe");
m_batchLogEdit->append(QString(" 期望位置:%1").arg(exePath));
} else {
m_batchLogEdit->append("✓ Python 工具准备就绪");
LogManager::instance()->logError(QString("未找到转换工具: %1").arg(exePath));
}
connect(m_pythonRunner, &PythonRunner::finished, this, &MainWindow::onPythonRunnerFinished);
connect(m_pythonRunner, &PythonRunner::standardOutput, this, &MainWindow::onPythonRunnerOutput);
connect(m_pythonRunner, &PythonRunner::standardError, this, &MainWindow::onPythonRunnerError);
connect(m_pythonRunner, &PythonRunner::started, [this]() {
m_batchLogEdit->append("转换任务已启动...");
});
connect(this, &ElaWindow::navigationNodeClicked, this, &MainWindow::onNavigationNodeClicked);
QTimer::singleShot(100, this, &MainWindow::updateNavigationButtonIcon);
}
void MainWindow::loadConfigCache()
{
LogManager::instance()->log("正在加载配置缓存...");
UF2ConfigReader uf2Reader;
bool uf2Loaded = uf2Reader.loadAllUF20Config();
UFT3ConfigReader uft3Reader;
bool uft3Loaded = uft3Reader.loadAllUFT3Config();
if (uf2Loaded && uft3Loaded) {
LogManager::instance()->log("✓ 配置缓存加载完成");
} else {
LogManager::instance()->logWarning("⚠️ 部分配置加载失败");
QStringList uf2Failed = uf2Reader.getFailedFiles();
QStringList uft3Failed = uft3Reader.getFailedFiles();
if (!uf2Failed.isEmpty()) {
LogManager::instance()->log(" UF20 加载失败:");
foreach (const QString& file, uf2Failed) {
LogManager::instance()->log(QString(" - %1").arg(file));
}
}
if (!uft3Failed.isEmpty()) {
LogManager::instance()->log(" UFT3 加载失败:");
foreach (const QString& file, uft3Failed) {
LogManager::instance()->log(QString(" - %1").arg(file));
}
}
}
}
MainWindow::~MainWindow()
@ -60,36 +104,41 @@ MainWindow::~MainWindow()
void MainWindow::initWindow()
{
setWindowTitle("UFT30 Change Code");
setWindowIcon(QIcon(":/Resource/Image/Cirno.jpg"));
setWindowTitle(QString("UFT30 Change Code %1").arg(Version::getVersionString()));
setWindowIcon(QIcon(":/resources/images/ChangeCode.png"));
resize(900, 600);
setUserInfoCardTitle("UFT30");
setUserInfoCardSubTitle("Change Code Tool");
setMinimumSize(800, 500);
setUserInfoCardVisible(false);
// 隐藏返回和前进按钮
setWindowButtonFlag(ElaAppBarType::RouteBackButtonHint, false);
setWindowButtonFlag(ElaAppBarType::RouteForwardButtonHint, false);
}
void MainWindow::initContent()
{
QString helpKey;
QString aboutKey;
QString settingKey;
addPageNode("转码业务", createBatchConvertPage(), ElaIconType::FileCode);
addPageNode("功能搜索", createFunctionSearchPage(), ElaIconType::MagnifyingGlass);
addFooterNode("帮助", createHelpPage(), helpKey, 0, ElaIconType::CircleQuestion);
addFooterNode("关于", createAboutPage(), aboutKey, 0, ElaIconType::User);
addFooterNode("设置", createSettingsPage(), settingKey, 0, ElaIconType::GearComplex);
addExpanderNode("功能转码", m_funcConvertKey, ElaIconType::FileCode);
addPageNode("业务转码", createBatchConvertPage(), m_funcConvertKey, ElaIconType::ArrowsRepeat);
addExpanderNode("功能查询", m_funcSearchKey, ElaIconType::MagnifyingGlass);
addPageNode("UF20功能查询", createUF20FunctionSearchPage(), m_funcSearchKey, ElaIconType::MagnifyingGlassPlus);
addPageNode("UFT3功能查询", createUFT3FunctionSearchPage(), m_funcSearchKey, ElaIconType::MagnifyingGlassPlus);
expandNavigationNode(m_funcConvertKey);
addPageNode("元数据更新", createMetadataUpdatePage(), ElaIconType::ArrowsRotate);
addFooterNode("帮助", m_helpKey, 0, ElaIconType::CircleQuestion);
addFooterNode("关于", m_aboutKey, 0, ElaIconType::Info);
addFooterNode("设置", createSettingsPage(), m_settingKey, 0, ElaIconType::GearComplex);
}
QWidget* MainWindow::createBatchConvertPage()
{
BatchConvertPage *page = new BatchConvertPage;
m_batchLogEdit = page->getLogEdit();
connect(page, &BatchConvertPage::startConvert, this, &MainWindow::onBatchConvertStart);
connect(m_pythonRunner, &PythonRunner::started, [this]() {
if (m_batchLogEdit) {
m_batchLogEdit->append("转换任务已启动...");
}
});
return page;
m_batchConvertPage = new BatchConvertPage;
connect(m_batchConvertPage, &BatchConvertPage::startConvert, this, &MainWindow::onBatchConvertStart);
connect(m_batchConvertPage, &BatchConvertPage::stopConvert, this, &MainWindow::onBatchConvertStop);
return m_batchConvertPage;
}
QWidget* MainWindow::createFunctionSearchPage()
@ -97,14 +146,17 @@ QWidget* MainWindow::createFunctionSearchPage()
return new FunctionSearchPage;
}
QWidget* MainWindow::createHelpPage()
QWidget* MainWindow::createUF20FunctionSearchPage()
{
return new HelpPage;
UF20FunctionSearchPage *page = new UF20FunctionSearchPage;
connect(page, &UF20FunctionSearchPage::addFunctionToConvert,
m_batchConvertPage, &BatchConvertPage::addFunction);
return page;
}
QWidget* MainWindow::createAboutPage()
QWidget* MainWindow::createUFT3FunctionSearchPage()
{
return new AboutPage;
return new UFT3FunctionSearchPage;
}
QWidget* MainWindow::createSettingsPage()
@ -112,10 +164,15 @@ QWidget* MainWindow::createSettingsPage()
return new SettingsPage();
}
QWidget* MainWindow::createMetadataUpdatePage()
{
return new MetadataUpdatePage();
}
void MainWindow::onBatchConvertStart()
{
if (m_pythonRunner->isRunning()) {
m_batchLogEdit->append("警告: 上一个任务还在运行中...");
LogManager::instance()->logWarning("警告: 上一个任务还在运行中...");
QMessageBox::warning(this, "提示", "上一个转换任务正在运行,请等待完成或停止当前任务。");
return;
}
@ -124,46 +181,213 @@ void MainWindow::onBatchConvertStart()
QString exePath = appDir + "/uf2touft3/uf2touft3.exe";
if (!m_pythonRunner->canRun()) {
m_batchLogEdit->append("错误: 找不到 uf2touft3/uf2touft3.exe!");
LogManager::instance()->logError("错误: 找不到 uf2touft3/uf2touft3.exe!");
QMessageBox::critical(this, "错误",
QString("无法启动转换任务!\n\n请确保:\nuf2touft3/uf2touft3.exe 存在,且该目录下包含 config.ini\n\n期望路径:\n%1")
.arg(exePath));
return;
}
m_batchLogEdit->append("========================================");
m_batchLogEdit->append("开始执行 UFT2 到 UFT3 的代码转换...");
m_batchLogEdit->append(QString("工具路径: %1").arg(exePath));
m_batchLogEdit->append("========================================");
if (m_batchConvertPage) {
m_totalFunctions = m_batchConvertPage->getFunctionCount();
m_functionList = m_batchConvertPage->getFunctionList();
m_currentFunctionIndex = 0;
} else {
m_totalFunctions = 0;
m_currentFunctionIndex = 0;
m_functionList.clear();
}
LogManager::instance()->log("========================================");
LogManager::instance()->log("开始执行 UFT2 到 UFT3 的代码转换...");
LogManager::instance()->log(QString("工具路径: %1").arg(exePath));
LogManager::instance()->log(QString("待转换函数数量: %1").arg(m_totalFunctions));
LogManager::instance()->log("========================================");
if (!m_pythonRunner->start()) {
m_batchLogEdit->append("错误: 无法启动转换进程!");
LogManager::instance()->logError("错误: 无法启动转换进程!");
} else {
if (m_batchConvertPage) {
m_batchConvertPage->onConvertStarted();
}
}
}
void MainWindow::onBatchConvertStop()
{
if (m_pythonRunner->isRunning()) {
LogManager::instance()->log("正在停止转换进程...");
m_pythonRunner->stop();
}
}
void MainWindow::onPythonRunnerFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
m_batchLogEdit->append("========================================");
if (m_batchConvertPage) {
m_batchConvertPage->onConvertFinished();
}
LogManager::instance()->log("========================================");
if (exitStatus == QProcess::NormalExit && exitCode == 0) {
m_batchLogEdit->append("✓ 代码转换完成!");
LogManager::instance()->log("✓ 代码转换完成!");
QMessageBox::information(this, "完成", "代码转换任务已成功完成!");
} else {
m_batchLogEdit->append(QString("✗ 转换失败! 退出码: %1").arg(exitCode));
LogManager::instance()->logError(QString("✗ 转换失败! 退出码: %1").arg(exitCode));
QMessageBox::warning(this, "失败", QString("代码转换任务失败,退出码: %1").arg(exitCode));
}
m_batchLogEdit->append("========================================");
LogManager::instance()->log("========================================");
}
void MainWindow::onPythonRunnerOutput(const QString &output)
{
if (!output.trimmed().isEmpty()) {
m_batchLogEdit->append(output);
LogManager::instance()->log(output);
QString trimmedOutput = output.trimmed();
QRegularExpression progressRegExp(R"(progress\s*[:=]\s*(\d+))");
QRegularExpressionMatch match = progressRegExp.match(trimmedOutput);
if (match.hasMatch()) {
int progress = match.captured(1).toInt();
QString status = trimmedOutput;
if (status.contains("progress", Qt::CaseInsensitive)) {
status = status.replace(progressRegExp, "").trimmed();
if (status.isEmpty()) {
status = QString("转换中 %1%").arg(progress);
}
}
if (m_batchConvertPage) {
m_batchConvertPage->onProgressUpdate(progress, status);
}
} else {
if (m_batchConvertPage) {
QString currentFunction;
QRegularExpression funcRegExp(R"(([\w_]+))");
QRegularExpressionMatch funcMatch = funcRegExp.match(trimmedOutput);
if (funcMatch.hasMatch()) {
currentFunction = funcMatch.captured(1);
}
if (!currentFunction.isEmpty() && m_totalFunctions > 0) {
int index = m_functionList.indexOf(currentFunction);
if (index >= 0 && index >= m_currentFunctionIndex) {
m_currentFunctionIndex = index + 1;
int progress = 20 + (m_currentFunctionIndex * 80) / m_totalFunctions;
QString status = QString("正在转换: %1").arg(currentFunction);
m_batchConvertPage->onProgressUpdate(progress, status);
return;
}
}
int currentProgress = 20;
if (trimmedOutput.contains("开始转换", Qt::CaseInsensitive)) {
currentProgress = 25;
} else if (trimmedOutput.contains("处理文件", Qt::CaseInsensitive)) {
currentProgress = 30;
} else if (trimmedOutput.contains("生成代码", Qt::CaseInsensitive)) {
currentProgress = 75;
} else if (trimmedOutput.contains("完成", Qt::CaseInsensitive)) {
currentProgress = 95;
}
m_batchConvertPage->onProgressUpdate(currentProgress, trimmedOutput);
}
}
}
}
void MainWindow::onPythonRunnerError(const QString &error)
{
if (!error.trimmed().isEmpty()) {
m_batchLogEdit->append(QString("[ERROR] %1").arg(error));
LogManager::instance()->logError(QString("[ERROR] %1").arg(error));
}
}
void MainWindow::updateNavigationButtonIcon()
{
// 使用资源文件中的图标
QIcon leftIcon(":/resources/images/zhedie_left.png");
if (leftIcon.isNull()) {
return;
}
// 查找所有 ElaToolButton
QList<ElaToolButton*> allButtons = this->findChildren<ElaToolButton*>(QString(), Qt::FindChildrenRecursively);
// 尝试查找导航按钮 - 可能在不同位置
for (int i = 0; i < allButtons.size(); i++) {
ElaToolButton* btn = allButtons[i];
QString objName = btn->objectName();
// 检查是否是导航按钮(可能的名称)
if (objName.contains("Nav", Qt::CaseInsensitive) ||
objName.contains("Menu", Qt::CaseInsensitive) ||
objName.contains("Navigation", Qt::CaseInsensitive)) {
m_navigationButton = btn;
break;
}
}
// 如果没有找到有名称的导航按钮,使用第一个可见按钮
if (!m_navigationButton) {
for (ElaToolButton* btn : allButtons) {
if (btn->isVisible()) {
m_navigationButton = btn;
break;
}
}
}
if (m_navigationButton) {
m_navigationButton->setProperty("ElaIconType", "");
m_navigationButton->setIcon(leftIcon);
m_navigationButton->setIconSize(QSize(24, 24));
m_navigationButton->update();
// 先断开可能存在的连接,然后重新连接,避免多次连接
disconnect(m_navigationButton, &ElaToolButton::clicked, this, &MainWindow::onNavigationButtonClicked);
connect(m_navigationButton, &ElaToolButton::clicked, this, &MainWindow::onNavigationButtonClicked);
}
}
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (!m_iconsSet && event->type() == QEvent::Show) {
// 窗口显示后尝试设置图标
updateNavigationButtonIcon();
m_iconsSet = true;
}
return ElaWindow::eventFilter(obj, event);
}
void MainWindow::onNavigationButtonClicked()
{
if (!m_navigationButton) {
return;
}
QIcon leftIcon(":/resources/images/zhedie_left.png");
QIcon rightIcon(":/resources/images/zhedie_right.png");
// 使用状态变量来判断当前状态,而不是依赖 cacheKey
if (m_isNavigationExpanded) {
// 当前是展开状态,切换到折叠状态
m_navigationButton->setIcon(rightIcon);
m_isNavigationExpanded = false;
} else {
// 当前是折叠状态,切换到展开状态
m_navigationButton->setIcon(leftIcon);
m_isNavigationExpanded = true;
}
m_navigationButton->update();
}
void MainWindow::onNavigationNodeClicked(ElaNavigationType::NavigationNodeType nodeType, QString nodeKey)
{
Q_UNUSED(nodeType);
if (nodeKey == m_helpKey) {
QDesktopServices::openUrl(QUrl("http://10.20.163.105:6045/uft3changecode"));
} else if (nodeKey == m_aboutKey) {
std::make_unique<AboutDialog>(this)->exec();
}
}

View File

@ -2,14 +2,18 @@
#define MAINWINDOW_H
#include "ElaWindow.h"
#include "ElaToolButton.h"
#include <QWidget>
#include <QTextEdit>
#include "src/pythonrunner/PythonRunner.h"
#include "src/pages/batchconvert/batchconvertpage.h"
#include "src/pages/functionsearch/functionsearchpage.h"
#include "src/pages/help/helppage.h"
#include "src/pages/about/aboutpage.h"
#include "src/pages/functionsearch/uf20functionsearchpage.h"
#include "src/pages/functionsearch/uft3functionsearchpage.h"
#include "src/pages/about/aboutdialog.h"
#include "src/pages/settings/settingspage.h"
#include "src/pages/metadatupdate/metadatupdatepage.h"
#include "src/utils/version.h"
class MainWindow : public ElaWindow
{
@ -25,17 +29,38 @@ private:
QWidget* createBatchConvertPage();
QWidget* createFunctionSearchPage();
QWidget* createHelpPage();
QWidget* createAboutPage();
QWidget* createUF20FunctionSearchPage();
QWidget* createUFT3FunctionSearchPage();
QWidget* createSettingsPage();
QWidget* createMetadataUpdatePage();
void loadConfigCache();
void onBatchConvertStart();
void onBatchConvertStop();
void onPythonRunnerFinished(int exitCode, QProcess::ExitStatus exitStatus);
void onPythonRunnerOutput(const QString &output);
void onPythonRunnerError(const QString &error);
void updateNavigationButtonIcon();
bool eventFilter(QObject *obj, QEvent *event) override;
void onNavigationButtonClicked();
void onNavigationNodeClicked(ElaNavigationType::NavigationNodeType nodeType, QString nodeKey);
PythonRunner *m_pythonRunner;
QTextEdit *m_batchLogEdit;
bool m_iconsSet;
ElaToolButton* m_navigationButton;
bool m_isNavigationExpanded;
BatchConvertPage *m_batchConvertPage;
int m_totalFunctions;
int m_currentFunctionIndex;
QStringList m_functionList;
QString m_helpKey;
QString m_aboutKey;
QString m_settingKey;
QString m_funcSearchKey;
QString m_funcConvertKey;
};
#endif // MAINWINDOW_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,529 @@
#include "metadataprocessor.h"
#include "uf2interface.h"
#include "uft3interface.h"
#include "filedb.h"
#include "uf2stdfields.h"
#include "uf2datatype.h"
#include "uf2errnumber.h"
#include "uft3stdfields.h"
#include "uft3datatype.h"
#include "uft3table.h"
#include "utils/logmanager.h"
#include "utils/configmanager.h"
#include <QFile>
#include <QFileInfo>
#include <QSettings>
#include <QDir>
MetadataProcessor::MetadataProcessor(QObject *parent) : QObject(parent)
{
}
void MetadataProcessor::initConfig(const QString& basePath)
{
m_basePath = basePath;
m_uf2touft3Path = QDir(basePath).filePath("uf2touft3");
LogManager::instance()->log("========== 初始化配置 ==========");
ConfigManager* configManager = ConfigManager::instance();
m_uf20Path = configManager->getValue("projectPath", "uf20");
m_ufAcct20Path = configManager->getValue("projectPath", "ufAcct20");
m_uftDbSettPath = configManager->getValue("projectPath", "UftdbSett");
m_uft30PubPath = configManager->getValue("projectPath", "uft30pub");
m_uft30CbptransPath = configManager->getValue("projectPath", "uft30cbptrans");
m_uft30Path = configManager->getValue("projectPath", "uft30");
m_supportUftdbSett = configManager->getValue("testConfig", "supportUftdbSett");
m_moduleGenerationCheck = configManager->getValue("testConfig", "moduleGenerationCheck");
LogManager::instance()->log(QString("UF2TOUFT3路径: %1").arg(m_uf2touft3Path));
LogManager::instance()->log(QString("UF20路径: %1").arg(m_uf20Path));
LogManager::instance()->log(QString("UF20会计路径: %1").arg(m_ufAcct20Path));
LogManager::instance()->log(QString("UFT数据库设置路径: %1").arg(m_uftDbSettPath));
LogManager::instance()->log(QString("UFT30公共路径: %1").arg(m_uft30PubPath));
LogManager::instance()->log(QString("UFT30交易路径: %1").arg(m_uft30CbptransPath));
LogManager::instance()->log(QString("UFT30路径: %1").arg(m_uft30Path));
}
bool MetadataProcessor::isValidUtf8(const QByteArray& data)
{
QString test = QString::fromUtf8(data);
return test.toUtf8() == data;
}
bool MetadataProcessor::writeJson(const QString& filePath, const QJsonObject& jsonObject)
{
LogManager::instance()->log(QString("准备写入JSON文件: %1, 对象大小: %2").arg(filePath).arg(jsonObject.size()));
QFile file(filePath);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
LogManager::instance()->logError(QString("无法打开文件: %1").arg(filePath));
return false;
}
QJsonDocument doc(jsonObject);
qint64 bytesWritten = file.write(doc.toJson(QJsonDocument::Indented));
file.close();
LogManager::instance()->log(QString("成功写入JSON文件: %1, 写入字节数: %2").arg(filePath).arg(bytesWritten));
return true;
}
QJsonObject MetadataProcessor::interfaceInfoToUFT3Json(const InterfaceInfo& info)
{
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;
return interfaceJson;
}
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 configPath = QDir(m_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 = m_uf20Path;
QString ufAcct20ProjectDir = m_ufAcct20Path;
QString uftDbSett = m_uftDbSettPath;
QString supportUftdbSett = m_supportUftdbSett;
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(m_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(m_uf2touft3Path).filePath("uf2.json");
if (!writeJson(outputPath, resultJson)) {
return false;
}
LogManager::instance()->log(QString("UF2.0 接口处理完成,结果已保存到: %1").arg(outputPath));
if (!resultMap.isEmpty()) {
QString firstKey = resultMap.keys().first();
}
return true;
}
bool MetadataProcessor::processUft3Interfaces(const QString& basePath)
{
LogManager::instance()->log("========== 开始处理 UFT3.0 接口 ==========");
LogManager::instance()->log(QString("基础路径(basePath): %1").arg(basePath));
QString configPath = QDir(m_uf2touft3Path).filePath("config.ini");
LogManager::instance()->log(QString("配置文件路径: %1").arg(configPath));
QString moduleGenerationCheck = m_moduleGenerationCheck;
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 = m_uft30Path;
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];
resultJson[key] = interfaceInfoToUFT3Json(info);
}
QString outputPath = QDir(m_uf2touft3Path).filePath("uft3.json");
if (!writeJson(outputPath, resultJson)) {
return false;
}
QJsonObject transCodeJson;
for (const QString& key : transCodeMap.keys()) {
const InterfaceInfo& info = transCodeMap[key];
transCodeJson[key] = interfaceInfoToUFT3Json(info);
}
QString transOutputPath = QDir(m_uf2touft3Path).filePath("uft3Trans.json");
if (!writeJson(transOutputPath, transCodeJson)) {
return false;
}
LogManager::instance()->log(QString("UFT3.0 接口处理完成,结果已保存到: %1").arg(outputPath));
return true;
}
bool MetadataProcessor::processUf2DataType()
{
LogManager::instance()->log("========== 开始处理 UF2.0 数据类型 ==========");
QString dirPath = m_uf20Path;
Uf2DataType uf2DataType;
auto resultMap = uf2DataType.loadData(dirPath);
QJsonObject resultJson;
for (const QString& key : resultMap.keys()) {
const QMap<QString, QString>& typeInfo = resultMap[key];
QJsonObject typeJson;
for (const QString& attrKey : typeInfo.keys()) {
typeJson[attrKey] = typeInfo[attrKey];
}
resultJson[key] = typeJson;
}
QString outputPath = QDir(m_uf2touft3Path).filePath("uf2dataType.json");
if (!writeJson(outputPath, resultJson)) {
return false;
}
LogManager::instance()->log(QString("UF2.0 数据类型处理完成,结果已保存到: %1").arg(outputPath));
return true;
}
bool MetadataProcessor::processUf2StdFields()
{
LogManager::instance()->log("========== 开始处理 UF2.0 标准字段 ==========");
QString dirPath = m_uf20Path;
QMap<QString, QMap<QString, QString>> uf2datatypeMap;
QString datatypeJsonPath = QDir(m_uf2touft3Path).filePath("uf2dataType.json");
QJsonObject datatypeJson = readJson(datatypeJsonPath);
for (const QString& key : datatypeJson.keys()) {
QJsonObject typeObj = datatypeJson[key].toObject();
QMap<QString, QString> typeInfo;
for (const QString& attrKey : typeObj.keys()) {
typeInfo[attrKey] = typeObj[attrKey].toString();
}
uf2datatypeMap[key] = typeInfo;
}
Uf2StdFields uf2StdFields;
auto resultMap = uf2StdFields.loadData(dirPath, uf2datatypeMap);
QJsonObject resultJson;
for (const QString& key : resultMap.keys()) {
const QMap<QString, QString>& fieldInfo = resultMap[key];
QJsonObject fieldJson;
for (const QString& attrKey : fieldInfo.keys()) {
fieldJson[attrKey] = fieldInfo[attrKey];
}
resultJson[key] = fieldJson;
}
QString outputPath = QDir(m_uf2touft3Path).filePath("uf2stdfield.json");
if (!writeJson(outputPath, resultJson)) {
return false;
}
LogManager::instance()->log(QString("UF2.0 标准字段处理完成,结果已保存到: %1").arg(outputPath));
return true;
}
bool MetadataProcessor::processUf2ErrNumber()
{
LogManager::instance()->log("========== 开始处理 UF2.0 标准错误号 ==========");
QString dirPath = m_uf20Path;
Uf2ErrNumber uf2ErrNumber;
auto resultMap = uf2ErrNumber.loadData(dirPath);
QJsonObject resultJson;
for (const QString& key : resultMap.keys()) {
const QMap<QString, QString>& errorInfo = resultMap[key];
QJsonObject errorJson;
for (const QString& attrKey : errorInfo.keys()) {
errorJson[attrKey] = errorInfo[attrKey];
}
resultJson[key] = errorJson;
}
QString outputPath = QDir(m_uf2touft3Path).filePath("uf2Error.json");
if (!writeJson(outputPath, resultJson)) {
return false;
}
LogManager::instance()->log(QString("UF2.0 标准错误号处理完成,结果已保存到: %1").arg(outputPath));
return true;
}
bool MetadataProcessor::processUft3DataType()
{
LogManager::instance()->log("========== 开始处理 UFT3.0 数据类型 ==========");
QString dirPath = m_uft30PubPath;
Uft3DataType uft3DataType;
auto resultMap = uft3DataType.loadData(dirPath);
QJsonObject resultJson;
for (const QString& key : resultMap.keys()) {
const QMap<QString, QString>& typeInfo = resultMap[key];
QJsonObject typeJson;
for (const QString& attrKey : typeInfo.keys()) {
typeJson[attrKey] = typeInfo[attrKey];
}
resultJson[key] = typeJson;
}
QString outputPath = QDir(m_uf2touft3Path).filePath("uft3datatype.json");
if (!writeJson(outputPath, resultJson)) {
return false;
}
LogManager::instance()->log(QString("UFT3.0 数据类型处理完成,结果已保存到: %1").arg(outputPath));
return true;
}
bool MetadataProcessor::processUft3StdFields()
{
LogManager::instance()->log("========== 开始处理 UFT3.0 标准字段 ==========");
QString dirPath = m_uft30PubPath;
QMap<QString, QMap<QString, QString>> uf3datatypeMap;
QString datatypeJsonPath = QDir(m_uf2touft3Path).filePath("uft3datatype.json");
QJsonObject datatypeJson = readJson(datatypeJsonPath);
for (const QString& key : datatypeJson.keys()) {
QJsonObject typeObj = datatypeJson[key].toObject();
QMap<QString, QString> typeInfo;
for (const QString& attrKey : typeObj.keys()) {
typeInfo[attrKey] = typeObj[attrKey].toString();
}
uf3datatypeMap[key] = typeInfo;
}
Uft3StdFields uft3StdFields;
auto resultMap = uft3StdFields.loadData(dirPath, uf3datatypeMap);
QJsonObject resultJson;
for (const QString& key : resultMap.keys()) {
const QMap<QString, QString>& fieldInfo = resultMap[key];
QJsonObject fieldJson;
for (const QString& attrKey : fieldInfo.keys()) {
fieldJson[attrKey] = fieldInfo[attrKey];
}
resultJson[key] = fieldJson;
}
QString outputPath = QDir(m_uf2touft3Path).filePath("uft3stdfields.json");
if (!writeJson(outputPath, resultJson)) {
return false;
}
LogManager::instance()->log(QString("UFT3.0 标准字段处理完成,结果已保存到: %1").arg(outputPath));
return true;
}
bool MetadataProcessor::processUft3Table()
{
LogManager::instance()->log("========== 开始处理 UFT3.0 表结构 ==========");
QString dirPath = m_uft30PubPath;
Uft3Table uft3Table;
auto resultMap = uft3Table.loadData(dirPath);
QJsonObject resultJson;
for (const QString& key : resultMap.keys()) {
const QMap<QString, QVariant>& tableInfo = resultMap[key];
QJsonObject tableJson;
for (const QString& attrKey : tableInfo.keys()) {
QVariant value = tableInfo[attrKey];
if (value.canConvert<QJsonValue>()) {
tableJson[attrKey] = value.toJsonValue();
}
}
resultJson[key] = tableJson;
}
QString outputPath = QDir(m_uf2touft3Path).filePath("uft3Table.json");
if (!writeJson(outputPath, resultJson)) {
return false;
}
LogManager::instance()->log(QString("UFT3.0 表结构处理完成,结果已保存到: %1").arg(outputPath));
return true;
}

View File

@ -0,0 +1,55 @@
#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);
bool processUf2StdFields();
bool processUf2DataType();
bool processUf2ErrNumber();
bool processUft3StdFields();
bool processUft3DataType();
bool processUft3Table();
QString getBasePath() const;
void setBasePath(const QString& path);
public:
void initConfig(const QString& basePath);
private:
bool isValidUtf8(const QByteArray& data);
bool writeJson(const QString& filePath, const QJsonObject& jsonObject);
QJsonObject readJson(const QString& filePath);
QJsonObject interfaceInfoToUFT3Json(const InterfaceInfo& info);
QString m_basePath;
QString m_uf2touft3Path;
QString m_uf20Path;
QString m_ufAcct20Path;
QString m_uftDbSettPath;
QString m_uft30PubPath;
QString m_uft30CbptransPath;
QString m_uft30Path;
QString m_supportUftdbSett;
QString m_moduleGenerationCheck;
};
#endif // METADATAPROCESSOR_H

View File

@ -0,0 +1,86 @@
#include "uf2datatype.h"
#include "utils/logmanager.h"
#include <QFile>
#include <QDir>
#include <QXmlStreamReader>
Uf2DataType::Uf2DataType(QObject *parent) : QObject(parent)
{
}
QMap<QString, QMap<QString, QString>> Uf2DataType::loadData(const QString& dirPath)
{
QMap<QString, QMap<QString, QString>> resultMap;
QString filePath = dirPath;
filePath.replace('\\', '/');
filePath += "/公共资源/datatypes.xml";
LogManager::instance()->log(QString("加载UF2数据类型文件: %1").arg(filePath));
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
LogManager::instance()->logError(QString("无法打开文件: %1").arg(filePath));
return resultMap;
}
QXmlStreamReader xml(&file);
while (!xml.atEnd() && !xml.hasError()) {
QXmlStreamReader::TokenType token = xml.readNext();
if (token == QXmlStreamReader::StartElement) {
QString elementName = xml.name().toString();
if (elementName == "userType") {
QXmlStreamAttributes attrs = xml.attributes();
QString hsType = attrs.value("name").toString();
QString cValue = "";
QString oValue = "";
while (!xml.atEnd() && !xml.hasError()) {
token = xml.readNext();
if (token == QXmlStreamReader::StartElement) {
QString childElementName = xml.name().toString();
if (childElementName == "language") {
while (!xml.atEnd() && !xml.hasError()) {
token = xml.readNext();
if (token == QXmlStreamReader::StartElement && xml.name().toString() == "map") {
cValue = xml.attributes().value("value").toString();
break;
}
}
}
else if (childElementName == "database") {
while (!xml.atEnd() && !xml.hasError()) {
token = xml.readNext();
if (token == QXmlStreamReader::StartElement && xml.name().toString() == "map") {
oValue = xml.attributes().value("value").toString();
break;
}
}
}
}
else if (token == QXmlStreamReader::EndElement && xml.name().toString() == "userType") {
break;
}
}
QMap<QString, QString> typeInfo;
typeInfo["HsType"] = hsType;
typeInfo["CType"] = cValue;
typeInfo["OType"] = oValue;
resultMap[hsType] = typeInfo;
}
}
}
file.close();
LogManager::instance()->log(QString("UF2数据类型加载完成共 %1 条").arg(resultMap.size()));
return resultMap;
}

View File

@ -0,0 +1,19 @@
#ifndef UF2DATATYPE_H
#define UF2DATATYPE_H
#include <QObject>
#include <QString>
#include <QMap>
class Uf2DataType : public QObject
{
Q_OBJECT
public:
explicit Uf2DataType(QObject *parent = nullptr);
QMap<QString, QMap<QString, QString>> loadData(const QString& dirPath);
private:
};
#endif

View File

@ -0,0 +1,56 @@
#include "uf2errnumber.h"
#include "utils/logmanager.h"
#include <QFile>
#include <QDir>
#include <QXmlStreamReader>
Uf2ErrNumber::Uf2ErrNumber(QObject *parent) : QObject(parent)
{
}
QMap<QString, QMap<QString, QString>> Uf2ErrNumber::loadData(const QString& dirPath)
{
QMap<QString, QMap<QString, QString>> resultMap;
QString filePath = dirPath;
filePath.replace('\\', '/');
filePath += "/公共资源/errNumbers.xml";
LogManager::instance()->log(QString("加载UF2错误号文件: %1").arg(filePath));
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
LogManager::instance()->logError(QString("无法打开文件: %1").arg(filePath));
return resultMap;
}
QXmlStreamReader xml(&file);
while (!xml.atEnd() && !xml.hasError()) {
QXmlStreamReader::TokenType token = xml.readNext();
if (token == QXmlStreamReader::StartElement) {
QString elementName = xml.name().toString();
if (elementName == "error_no") {
QXmlStreamAttributes attrs = xml.attributes();
QString sErrorNo = attrs.value("code").toString();
QString sConstant = attrs.value("constant").toString();
QString sErrorInfo = attrs.value("info").toString();
QMap<QString, QString> errorInfo;
errorInfo["code"] = sErrorNo;
errorInfo["constant"] = sConstant;
errorInfo["info"] = sErrorInfo;
resultMap[sConstant] = errorInfo;
}
}
}
file.close();
LogManager::instance()->log(QString("UF2错误号加载完成共 %1 条").arg(resultMap.size()));
return resultMap;
}

View File

@ -0,0 +1,19 @@
#ifndef UF2ERRNUMBER_H
#define UF2ERRNUMBER_H
#include <QObject>
#include <QString>
#include <QMap>
class Uf2ErrNumber : public QObject
{
Q_OBJECT
public:
explicit Uf2ErrNumber(QObject *parent = nullptr);
QMap<QString, QMap<QString, QString>> loadData(const QString& dirPath);
private:
};
#endif

View File

@ -0,0 +1,273 @@
#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 (elementName == "code") {
result.code = xml.readElementText();
if (filePath.contains("不用编译")) {
result.code.clear();
}
}
}
else if (token == QXmlStreamReader::EndElement) {
if (!elementStack.isEmpty()) {
elementStack.pop();
}
}
}
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 == "info") {
QXmlStreamAttributes attrs = xml.attributes();
if (attrs.hasAttribute("ename")) {
return attrs.value("ename").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)) {
return true;
}
for (const QString& name : containNameList) {
if (filePath.contains(name, Qt::CaseInsensitive)) {
return true;
}
}
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";
std::function<void(const QString&)> scanModuleXmlRecursive;
scanModuleXmlRecursive = [&](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;
}
QFileInfoList dirList = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
for (const QFileInfo& dirInfo : dirList) {
scanModuleXmlRecursive(dirInfo.absoluteFilePath());
}
};
auto scanModuleXml = [&](const QString& path) {
scanModuleXmlRecursive(path);
};
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 sFilePath = filePath;
int lastSlash = sFilePath.lastIndexOf('/');
QString pathWithoutFile = sFilePath.left(lastSlash);
int secondLastSlash = pathWithoutFile.lastIndexOf('/');
QString pathWithoutLastDir = pathWithoutFile.left(secondLastSlash);
int thirdLastSlash = pathWithoutLastDir.lastIndexOf('/');
QString modName = pathWithoutLastDir.mid(thirdLastSlash + 1);
InterfaceInfo interfaceInfo = loadInterface(filePath);
interfaceInfo.moudle = modName;
QString moudleEName = moduleCodeMap.value(modName);
interfaceInfo.moudleEName = moudleEName;
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,73 @@
#include "uf2stdfields.h"
#include "utils/logmanager.h"
#include <QFile>
#include <QDir>
#include <QXmlStreamReader>
Uf2StdFields::Uf2StdFields(QObject *parent) : QObject(parent)
{
}
QMap<QString, QMap<QString, QString>> Uf2StdFields::loadData(
const QString& dirPath,
const QMap<QString, QMap<QString, QString>>& uf2datatypeMap)
{
QMap<QString, QMap<QString, QString>> resultMap;
QString filePath = dirPath;
filePath.replace('\\', '/');
filePath += "/公共资源/stdfields.xml";
LogManager::instance()->log(QString("加载UF2标准字段文件: %1").arg(filePath));
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
LogManager::instance()->logError(QString("无法打开文件: %1").arg(filePath));
return resultMap;
}
QXmlStreamReader xml(&file);
while (!xml.atEnd() && !xml.hasError()) {
QXmlStreamReader::TokenType token = xml.readNext();
if (token == QXmlStreamReader::StartElement) {
QString elementName = xml.name().toString();
if (elementName == "stdfield") {
QXmlStreamAttributes attrs = xml.attributes();
QString sFieldName = attrs.value("name").toString();
QString sCname = attrs.value("cname").toString();
QString sType = attrs.value("type").toString();
QString sDesc = attrs.value("desc").toString();
sDesc.replace("'", "\"");
QString sDictId = attrs.value("dict").toString();
QString sCtype = "";
QString sOType = "";
if (uf2datatypeMap.contains(sType)) {
sCtype = uf2datatypeMap[sType].value("CType");
sOType = uf2datatypeMap[sType].value("OType");
}
QMap<QString, QString> fieldInfo;
fieldInfo["name"] = sFieldName;
fieldInfo["cname"] = sCname;
fieldInfo["type"] = sType;
fieldInfo["desc"] = sDesc;
fieldInfo["dict"] = sDictId;
fieldInfo["cType"] = sCtype;
fieldInfo["oType"] = sOType;
resultMap[sFieldName] = fieldInfo;
}
}
}
file.close();
LogManager::instance()->log(QString("UF2标准字段加载完成共 %1 条").arg(resultMap.size()));
return resultMap;
}

View File

@ -0,0 +1,20 @@
#ifndef UF2STDFIELDS_H
#define UF2STDFIELDS_H
#include <QObject>
#include <QString>
#include <QMap>
class Uf2StdFields : public QObject
{
Q_OBJECT
public:
explicit Uf2StdFields(QObject *parent = nullptr);
QMap<QString, QMap<QString, QString>> loadData(const QString& dirPath,
const QMap<QString, QMap<QString, QString>>& uf2datatypeMap);
private:
};
#endif

View File

@ -0,0 +1,72 @@
#include "uft3datatype.h"
#include "utils/logmanager.h"
#include <QFile>
#include <QDir>
#include <QXmlStreamReader>
Uft3DataType::Uft3DataType(QObject *parent) : QObject(parent)
{
}
QMap<QString, QMap<QString, QString>> Uft3DataType::loadData(const QString& dirPath)
{
QMap<QString, QMap<QString, QString>> resultMap;
QString filePath = dirPath;
filePath.replace('\\', '/');
filePath += "/metadata/datatype.datatype";
LogManager::instance()->log(QString("加载UFT3数据类型文件: %1").arg(filePath));
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
LogManager::instance()->logError(QString("无法打开文件: %1").arg(filePath));
return resultMap;
}
QXmlStreamReader xml(&file);
while (!xml.atEnd() && !xml.hasError()) {
QXmlStreamReader::TokenType token = xml.readNext();
if (token == QXmlStreamReader::StartElement) {
QString elementName = xml.name().toString();
if (elementName == "items") {
QXmlStreamAttributes attrs = xml.attributes();
QString hsType = attrs.value("name").toString();
QString uftValue = attrs.value("stdType").toString();
QString uftLen = "0";
if (uftValue.toLower() == "string") {
uftLen = attrs.value("length").toString();
uftValue = "char[" + uftLen + "]";
}
else if (uftValue.toLower() == "int32") {
uftValue = "int";
}
else if (uftValue.toLower() == "int64") {
uftValue = "double";
}
else if (uftValue.toLower() == "double") {
uftValue = "double";
}
else if (uftValue.toLower() == "char") {
uftValue = "char";
}
QMap<QString, QString> typeInfo;
typeInfo["HsType"] = hsType;
typeInfo["uftType"] = uftValue;
resultMap[hsType] = typeInfo;
}
}
}
file.close();
LogManager::instance()->log(QString("UFT3数据类型加载完成共 %1 条").arg(resultMap.size()));
return resultMap;
}

View File

@ -0,0 +1,19 @@
#ifndef TFT3DATATYPE_H
#define TFT3DATATYPE_H
#include <QObject>
#include <QString>
#include <QMap>
class Uft3DataType : public QObject
{
Q_OBJECT
public:
explicit Uft3DataType(QObject *parent = nullptr);
QMap<QString, QMap<QString, QString>> loadData(const QString& dirPath);
private:
};
#endif

View File

@ -0,0 +1,245 @@
#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());
if (completeNameList.contains(fileName)) {
return true;
}
int dotPos = relPath.indexOf('.');
QString suffix;
if (dotPos != -1) {
suffix = relPath.mid(dotPos);
}
if (!containNameList.contains(suffix)) {
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

@ -0,0 +1,70 @@
#include "uft3stdfields.h"
#include "utils/logmanager.h"
#include <QFile>
#include <QDir>
#include <QXmlStreamReader>
Uft3StdFields::Uft3StdFields(QObject *parent) : QObject(parent)
{
}
QMap<QString, QMap<QString, QString>> Uft3StdFields::loadData(
const QString& dirPath,
const QMap<QString, QMap<QString, QString>>& uf3datatypeMap)
{
QMap<QString, QMap<QString, QString>> resultMap;
QString filePath = dirPath;
filePath.replace('\\', '/');
filePath += "/metadata/stdfield.stdfield";
LogManager::instance()->log(QString("加载UFT3标准字段文件: %1").arg(filePath));
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
LogManager::instance()->logError(QString("无法打开文件: %1").arg(filePath));
return resultMap;
}
QXmlStreamReader xml(&file);
while (!xml.atEnd() && !xml.hasError()) {
QXmlStreamReader::TokenType token = xml.readNext();
if (token == QXmlStreamReader::StartElement) {
QString elementName = xml.name().toString();
if (elementName == "items") {
QXmlStreamAttributes attrs = xml.attributes();
QString sFieldName = attrs.value("name").toString();
QString sCname = attrs.value("chineseName").toString();
QString sType = attrs.value("dataType").toString();
QString sDesc = attrs.value("description").toString();
sDesc.replace("'", "\"");
QString sDictId = attrs.value("dictionaryType").toString();
QString sUftType = "";
if (uf3datatypeMap.contains(sType)) {
sUftType = uf3datatypeMap[sType].value("uftType");
}
QMap<QString, QString> fieldInfo;
fieldInfo["name"] = sFieldName;
fieldInfo["cname"] = sCname;
fieldInfo["type"] = sType;
fieldInfo["desc"] = sDesc;
fieldInfo["dict"] = sDictId;
fieldInfo["uftType"] = sUftType;
resultMap[sFieldName] = fieldInfo;
}
}
}
file.close();
LogManager::instance()->log(QString("UFT3标准字段加载完成共 %1 条").arg(resultMap.size()));
return resultMap;
}

View File

@ -0,0 +1,20 @@
#ifndef TFT3STDFIELDS_H
#define TFT3STDFIELDS_H
#include <QObject>
#include <QString>
#include <QMap>
class Uft3StdFields : public QObject
{
Q_OBJECT
public:
explicit Uft3StdFields(QObject *parent = nullptr);
QMap<QString, QMap<QString, QString>> loadData(const QString& dirPath,
const QMap<QString, QMap<QString, QString>>& uf3datatypeMap);
private:
};
#endif

View File

@ -0,0 +1,198 @@
#include "uft3table.h"
#include "utils/logmanager.h"
#include <QFile>
#include <QDir>
#include <QXmlStreamReader>
#include <QJsonObject>
#include <QJsonArray>
Uft3Table::Uft3Table(QObject *parent) : QObject(parent)
{
}
QMap<QString, QMap<QString, QVariant>> Uft3Table::loadData(const QString& dirPath)
{
QMap<QString, QMap<QString, QVariant>> resultMap;
QString scanPath = dirPath;
scanPath.replace('\\', '/');
scanPath += "/uftstructure";
LogManager::instance()->log(QString("加载UFT3表结构目录: %1").arg(scanPath));
QDir dir(scanPath);
if (!dir.exists()) {
LogManager::instance()->logError(QString("表结构目录不存在: %1").arg(scanPath));
return resultMap;
}
scanDirectory(scanPath, resultMap);
for (const QString& filePath : _fileList) {
if (filePath.contains(".uftstructure")) {
parseTableFile(filePath, resultMap);
}
}
LogManager::instance()->log(QString("UFT3表结构加载完成共 %1 条").arg(resultMap.size()));
return resultMap;
}
void Uft3Table::scanDirectory(const QString& dirPath, QMap<QString, QMap<QString, QVariant>>& resultMap)
{
QDir dir(dirPath);
QFileInfoList fileList = dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
for (const QFileInfo& fileInfo : fileList) {
if (fileInfo.isDir()) {
scanDirectory(fileInfo.absoluteFilePath(), resultMap);
}
else if (fileInfo.isFile()) {
_fileList.append(fileInfo.absoluteFilePath());
}
}
}
void Uft3Table::parseTableFile(const QString& filePath, QMap<QString, QMap<QString, QVariant>>& resultMap)
{
QString sFilePath = filePath;
sFilePath.replace('\\', '/');
QFile file(sFilePath);
if (!file.open(QIODevice::ReadOnly)) {
LogManager::instance()->logError(QString("无法打开表结构文件: %1").arg(sFilePath));
return;
}
QByteArray data = file.readAll();
file.close();
QXmlStreamReader xml(data);
QString tableEngName = "";
QString tablePath = "";
QString chineseName = "";
QString objectId = "";
QString spaceName = "";
QStringList fieldList;
QMap<QString, QStringList> indexMap;
QMap<QString, QStringList> uniqueIndexMap;
QMap<QString, QStringList> globalIndexMap;
int lastSlash = sFilePath.lastIndexOf('/');
if (lastSlash != -1) {
tableEngName = sFilePath.mid(lastSlash + 1);
tableEngName = tableEngName.left(tableEngName.indexOf(".uftstructure"));
}
int uftstructurePos = sFilePath.indexOf("uftstructure");
if (uftstructurePos != -1) {
tablePath = sFilePath.mid(uftstructurePos);
}
while (!xml.atEnd() && !xml.hasError()) {
QXmlStreamReader::TokenType token = xml.readNext();
if (token == QXmlStreamReader::StartElement) {
QString elementName = xml.name().toString();
QXmlStreamAttributes attrs = xml.attributes();
if (elementName == "Structure") {
if (attrs.hasAttribute("chineseName")) {
chineseName = attrs.value("chineseName").toString();
}
if (attrs.hasAttribute("objectId")) {
objectId = attrs.value("objectId").toString();
}
if (attrs.hasAttribute("space")) {
spaceName = attrs.value("space").toString();
}
}
else if (elementName == "properties") {
QString fieldId = attrs.value("id").toString();
if (!fieldId.isEmpty()) {
fieldList.append(fieldId);
}
}
else if (elementName == "indexs") {
QString indexName = attrs.value("name").toString();
QStringList indexFieldList;
bool isUnique = !attrs.hasAttribute("containerType");
bool isGlobal = false;
if (attrs.hasAttribute("global") && attrs.value("global").toString() == "true") {
isGlobal = true;
}
while (!xml.atEnd() && !xml.hasError()) {
token = xml.readNext();
if (token == QXmlStreamReader::StartElement && xml.name().toString() == "items") {
QString fieldAttr = xml.attributes().value("attrname").toString();
if (!fieldAttr.isEmpty()) {
indexFieldList.append(fieldAttr);
}
}
else if (token == QXmlStreamReader::EndElement && xml.name().toString() == "indexs") {
break;
}
}
if (!indexName.isEmpty() && !indexFieldList.isEmpty()) {
indexMap[indexName] = indexFieldList;
if (isUnique) {
uniqueIndexMap[indexName] = indexFieldList;
}
if (isGlobal) {
globalIndexMap[indexName] = indexFieldList;
}
}
}
}
}
QString sUser = "";
if (spaceName == "HS_UFT_DATA") {
sUser = "hs_uft";
}
else if (spaceName == "HS_UARG_DATA") {
sUser = "hs_uarg";
}
else if (spaceName == "HS_USMS_DATA") {
sUser = "hs_usms";
}
QMap<QString, QVariant> tableInfoDetail;
tableInfoDetail["tableEngName"] = tableEngName;
tableInfoDetail["tablePath"] = tablePath;
tableInfoDetail["chineseName"] = chineseName;
tableInfoDetail["objectId"] = objectId;
tableInfoDetail["fieldList"] = fieldList;
tableInfoDetail["user"] = sUser;
QJsonObject indexMapJson;
for (const QString& key : indexMap.keys()) {
indexMapJson[key] = QJsonArray::fromStringList(indexMap[key]);
}
tableInfoDetail["indexMap"] = indexMapJson;
QJsonObject uniqueIndexMapJson;
for (const QString& key : uniqueIndexMap.keys()) {
uniqueIndexMapJson[key] = QJsonArray::fromStringList(uniqueIndexMap[key]);
}
tableInfoDetail["uniqueIndexMap"] = uniqueIndexMapJson;
QJsonObject globalIndexMapJson;
for (const QString& key : globalIndexMap.keys()) {
globalIndexMapJson[key] = QJsonArray::fromStringList(globalIndexMap[key]);
}
tableInfoDetail["globalIndexMap"] = globalIndexMapJson;
if (!tableEngName.isEmpty()) {
resultMap[tableEngName] = tableInfoDetail;
}
}

Some files were not shown because too many files have changed in this diff Show More