Compare commits

..

No commits in common. "main" and "master" have entirely different histories.
main ... master

133 changed files with 515 additions and 6241 deletions

10
.gitignore vendored
View File

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

View File

@ -1,24 +0,0 @@
# 图标设置说明
## 已完成配置
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
```
### 重新编译
设置好图标后重新编译项目即可。

View File

View File

@ -1,89 +0,0 @@
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 "resources/images/ChangeCode.ico"
IDI_ICON1 ICON DISCARDABLE "app.ico"

View File

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

View File

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

View File

@ -1 +0,0 @@
Uft30ChangeCodeHelp

View File

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

View File

@ -1,8 +0,0 @@
<?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>

View File

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

View File

@ -1,9 +0,0 @@
<?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

@ -1,6 +0,0 @@
<?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

@ -1,8 +0,0 @@
<?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>

View File

@ -1,6 +0,0 @@
<?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

@ -1,10 +0,0 @@
<?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

@ -1,7 +0,0 @@
<?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>

View File

@ -1,23 +0,0 @@
<?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.

Before

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

View File

@ -1,13 +0,0 @@
<?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

@ -1,17 +0,0 @@
# 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

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

View File

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

View File

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

View File

@ -1,18 +0,0 @@
# 下载
## 全量更新
下载全量包,解压即用。
> 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

@ -1,27 +0,0 @@
# 业务转码
将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

@ -1,25 +0,0 @@
# 元数据更新
更新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

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

View File

@ -1,32 +0,0 @@
# 功能转码
提供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

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

View File

@ -1,27 +0,0 @@
# 设置
## 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``
## 主题切换
包含日间模式和夜间模式。

View File

@ -1,5 +0,0 @@
<?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

@ -1,11 +0,0 @@
<?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>

View File

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

View File

@ -1,35 +0,0 @@
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

@ -1,89 +0,0 @@
#!/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

View File

@ -1,56 +0,0 @@
#!/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

View File

@ -1,10 +0,0 @@
#!/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

View File

@ -1,19 +0,0 @@
#!/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,20 +1,12 @@
#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.showMaximized();
w.show();
return a.exec();
}

View File

@ -1,11 +1,4 @@
<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>

View File

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

View File

@ -1,164 +0,0 @@
# 使用帮助
## 概述
欢迎使用 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 会自动同步转码列表
- 大文件转换可能需要较长时间,请耐心等待

View File

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

View File

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

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -1,116 +0,0 @@
#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

@ -1,46 +0,0 @@
#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

@ -1,116 +0,0 @@
#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

@ -1,68 +0,0 @@
#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,10 +2,6 @@
#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>
@ -20,82 +16,42 @@
#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();
loadConfigCache();
// 配置 Python 运行器 - 只使用打包好的 exe路径是 uf2touft3/uf2touft3.exe
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()) {
LogManager::instance()->logError(QString("未找到转换工具: %1").arg(exePath));
m_batchLogEdit->append("⚠️ 警告:未找到 uf2touft3/uf2touft3.exe");
m_batchLogEdit->append(QString(" 期望位置:%1").arg(exePath));
} else {
m_batchLogEdit->append("✓ Python 工具准备就绪");
}
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(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));
}
}
}
connect(m_pythonRunner, &PythonRunner::started, [this]() {
m_batchLogEdit->append("转换任务已启动...");
});
}
MainWindow::~MainWindow()
@ -104,41 +60,36 @@ MainWindow::~MainWindow()
void MainWindow::initWindow()
{
setWindowTitle(QString("UFT30 Change Code %1").arg(Version::getVersionString()));
setWindowIcon(QIcon(":/resources/images/ChangeCode.png"));
setWindowTitle("UFT30 Change Code");
setWindowIcon(QIcon(":/Resource/Image/Cirno.jpg"));
resize(900, 600);
setMinimumSize(800, 500);
setUserInfoCardVisible(false);
// 隐藏返回和前进按钮
setWindowButtonFlag(ElaAppBarType::RouteBackButtonHint, false);
setWindowButtonFlag(ElaAppBarType::RouteForwardButtonHint, false);
setUserInfoCardTitle("UFT30");
setUserInfoCardSubTitle("Change Code Tool");
}
void MainWindow::initContent()
{
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);
{
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);
}
QWidget* MainWindow::createBatchConvertPage()
{
m_batchConvertPage = new BatchConvertPage;
connect(m_batchConvertPage, &BatchConvertPage::startConvert, this, &MainWindow::onBatchConvertStart);
connect(m_batchConvertPage, &BatchConvertPage::stopConvert, this, &MainWindow::onBatchConvertStop);
return m_batchConvertPage;
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;
}
QWidget* MainWindow::createFunctionSearchPage()
@ -146,17 +97,14 @@ QWidget* MainWindow::createFunctionSearchPage()
return new FunctionSearchPage;
}
QWidget* MainWindow::createUF20FunctionSearchPage()
QWidget* MainWindow::createHelpPage()
{
UF20FunctionSearchPage *page = new UF20FunctionSearchPage;
connect(page, &UF20FunctionSearchPage::addFunctionToConvert,
m_batchConvertPage, &BatchConvertPage::addFunction);
return page;
return new HelpPage;
}
QWidget* MainWindow::createUFT3FunctionSearchPage()
QWidget* MainWindow::createAboutPage()
{
return new UFT3FunctionSearchPage;
return new AboutPage;
}
QWidget* MainWindow::createSettingsPage()
@ -164,15 +112,10 @@ QWidget* MainWindow::createSettingsPage()
return new SettingsPage();
}
QWidget* MainWindow::createMetadataUpdatePage()
{
return new MetadataUpdatePage();
}
void MainWindow::onBatchConvertStart()
{
if (m_pythonRunner->isRunning()) {
LogManager::instance()->logWarning("警告: 上一个任务还在运行中...");
m_batchLogEdit->append("警告: 上一个任务还在运行中...");
QMessageBox::warning(this, "提示", "上一个转换任务正在运行,请等待完成或停止当前任务。");
return;
}
@ -181,213 +124,46 @@ void MainWindow::onBatchConvertStart()
QString exePath = appDir + "/uf2touft3/uf2touft3.exe";
if (!m_pythonRunner->canRun()) {
LogManager::instance()->logError("错误: 找不到 uf2touft3/uf2touft3.exe!");
m_batchLogEdit->append("错误: 找不到 uf2touft3/uf2touft3.exe!");
QMessageBox::critical(this, "错误",
QString("无法启动转换任务!\n\n请确保:\nuf2touft3/uf2touft3.exe 存在,且该目录下包含 config.ini\n\n期望路径:\n%1")
.arg(exePath));
return;
}
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("========================================");
m_batchLogEdit->append("========================================");
m_batchLogEdit->append("开始执行 UFT2 到 UFT3 的代码转换...");
m_batchLogEdit->append(QString("工具路径: %1").arg(exePath));
m_batchLogEdit->append("========================================");
if (!m_pythonRunner->start()) {
LogManager::instance()->logError("错误: 无法启动转换进程!");
} else {
if (m_batchConvertPage) {
m_batchConvertPage->onConvertStarted();
}
}
}
void MainWindow::onBatchConvertStop()
{
if (m_pythonRunner->isRunning()) {
LogManager::instance()->log("正在停止转换进程...");
m_pythonRunner->stop();
m_batchLogEdit->append("错误: 无法启动转换进程!");
}
}
void MainWindow::onPythonRunnerFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
if (m_batchConvertPage) {
m_batchConvertPage->onConvertFinished();
}
LogManager::instance()->log("========================================");
m_batchLogEdit->append("========================================");
if (exitStatus == QProcess::NormalExit && exitCode == 0) {
LogManager::instance()->log("✓ 代码转换完成!");
m_batchLogEdit->append("✓ 代码转换完成!");
QMessageBox::information(this, "完成", "代码转换任务已成功完成!");
} else {
LogManager::instance()->logError(QString("✗ 转换失败! 退出码: %1").arg(exitCode));
m_batchLogEdit->append(QString("✗ 转换失败! 退出码: %1").arg(exitCode));
QMessageBox::warning(this, "失败", QString("代码转换任务失败,退出码: %1").arg(exitCode));
}
LogManager::instance()->log("========================================");
m_batchLogEdit->append("========================================");
}
void MainWindow::onPythonRunnerOutput(const QString &output)
{
if (!output.trimmed().isEmpty()) {
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);
}
}
m_batchLogEdit->append(output);
}
}
void MainWindow::onPythonRunnerError(const QString &error)
{
if (!error.trimmed().isEmpty()) {
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();
m_batchLogEdit->append(QString("[ERROR] %1").arg(error));
}
}

View File

@ -2,18 +2,14 @@
#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/functionsearch/uf20functionsearchpage.h"
#include "src/pages/functionsearch/uft3functionsearchpage.h"
#include "src/pages/about/aboutdialog.h"
#include "src/pages/help/helppage.h"
#include "src/pages/about/aboutpage.h"
#include "src/pages/settings/settingspage.h"
#include "src/pages/metadatupdate/metadatupdatepage.h"
#include "src/utils/version.h"
class MainWindow : public ElaWindow
{
@ -29,38 +25,17 @@ private:
QWidget* createBatchConvertPage();
QWidget* createFunctionSearchPage();
QWidget* createUF20FunctionSearchPage();
QWidget* createUFT3FunctionSearchPage();
QWidget* createHelpPage();
QWidget* createAboutPage();
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;
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;
QTextEdit *m_batchLogEdit;
};
#endif // MAINWINDOW_H

View File

@ -1,15 +0,0 @@
#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

@ -1,20 +0,0 @@
#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

@ -1,529 +0,0 @@
#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

@ -1,55 +0,0 @@
#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

@ -1,86 +0,0 @@
#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

@ -1,19 +0,0 @@
#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

@ -1,56 +0,0 @@
#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

@ -1,19 +0,0 @@
#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

@ -1,273 +0,0 @@
#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

@ -1,62 +0,0 @@
#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

@ -1,73 +0,0 @@
#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

@ -1,20 +0,0 @@
#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

@ -1,72 +0,0 @@
#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

@ -1,19 +0,0 @@
#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

@ -1,245 +0,0 @@
#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

@ -1,39 +0,0 @@
#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

@ -1,70 +0,0 @@
#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

@ -1,20 +0,0 @@
#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

@ -1,198 +0,0 @@
#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