From cdbed3d535182a510bce409b1e91fc7ad8b544fc Mon Sep 17 00:00:00 2001 From: hejl Date: Sat, 24 May 2025 14:35:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9Ecpp=5Fserver?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + .gitmodules | 3 + cpp_server/.vscode/c_cpp_properties.json | 22 ++++ cpp_server/.vscode/settings.json | 9 ++ cpp_server/CMakeLists.txt | 35 ++++++ cpp_server/RuntimeCompiledCPlusPlus | 1 + cpp_server/cmake/FindRCCPP.cmake | 7 ++ cpp_server/src/controllers/UserController.cpp | 21 ++++ cpp_server/src/controllers/UserController.h | 22 ++++ cpp_server/src/main.cpp | 48 ++++++++ documents/~$ UFT模块迁移方案.docx | Bin 162 -> 0 bytes win_text_editor/lib/menus/app_menu.dart | 35 +++++- win_text_editor/lib/menus/menu_actions.dart | 5 + win_text_editor/lib/menus/menu_constants.dart | 4 + .../controllers/data_compare_controller.dart | 1 - .../lib/modules/demo/widgets/demo_view.dart | 107 +----------------- .../lib/modules/module_router.dart | 5 + .../controllers/uft_file_controller.dart | 13 +++ .../uft_file/widgets/uft_file_view.dart | 47 ++++++++ 19 files changed, 274 insertions(+), 112 deletions(-) create mode 100644 .gitmodules create mode 100644 cpp_server/.vscode/c_cpp_properties.json create mode 100644 cpp_server/.vscode/settings.json create mode 100644 cpp_server/CMakeLists.txt create mode 160000 cpp_server/RuntimeCompiledCPlusPlus create mode 100644 cpp_server/cmake/FindRCCPP.cmake create mode 100644 cpp_server/src/controllers/UserController.cpp create mode 100644 cpp_server/src/controllers/UserController.h create mode 100644 cpp_server/src/main.cpp delete mode 100644 documents/~$ UFT模块迁移方案.docx create mode 100644 win_text_editor/lib/modules/uft_file/controllers/uft_file_controller.dart create mode 100644 win_text_editor/lib/modules/uft_file/widgets/uft_file_view.dart diff --git a/.gitignore b/.gitignore index ffdc333..ce63f09 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ /win_text_editor/macos /win_text_editor/web /win_text_editor/windows/runner +/cpp_server/swagger diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..ef65031 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "cpp_server/RuntimeCompiledCPlusPlus"] + path = cpp_server/RuntimeCompiledCPlusPlus + url = https://github.com/RuntimeCompiledCPlusPlus/RuntimeCompiledCPlusPlus.git diff --git a/cpp_server/.vscode/c_cpp_properties.json b/cpp_server/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..e0aa4cb --- /dev/null +++ b/cpp_server/.vscode/c_cpp_properties.json @@ -0,0 +1,22 @@ +{ + "configurations": [ + { + "name": "Win32", + "includePath": [ + "${workspaceFolder}/**", + "D:/aigc/vcpkg/installed/x64-windows/include/**" + ], + "defines": [ + "_DEBUG", + "UNICODE", + "_UNICODE" + ], + "windowsSdkVersion": "10.0.18362.0", + "compilerPath": "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x64/cl.exe", + "cStandard": "c11", + "cppStandard": "c++11", + "intelliSenseMode": "windows-msvc-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/cpp_server/.vscode/settings.json b/cpp_server/.vscode/settings.json new file mode 100644 index 0000000..435248e --- /dev/null +++ b/cpp_server/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "cmake.configureOnOpen": true, + "cmake.buildDirectory": "${workspaceFolder}/build", + "cmake.generator": "Visual Studio 16 2019 Win64", + "C_Cpp.default.cppStandard": "c++11", + "cmake.configureSettings": { + "CMAKE_TOOLCHAIN_FILE": "D:/aigc/vcpkg/scripts/buildsystems/vcpkg.cmake" + } +} \ No newline at end of file diff --git a/cpp_server/CMakeLists.txt b/cpp_server/CMakeLists.txt new file mode 100644 index 0000000..c61ddd7 --- /dev/null +++ b/cpp_server/CMakeLists.txt @@ -0,0 +1,35 @@ +cmake_minimum_required(VERSION 3.15) +project(MyDrogonProject) + +# 设置C++11标准 +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# 查找依赖 +find_package(Drogon CONFIG REQUIRED) + +# 添加RCC++子模块 +add_subdirectory(RuntimeCompiledCPlusPlus) + +# 定义热重载源文件 +set(RUNTIME_COMPILED_SOURCES + src/controllers/UserController.cpp +) + +# 主可执行文件 +add_executable(${PROJECT_NAME} + src/main.cpp + ${RUNTIME_COMPILED_SOURCES} +) + +# 配置RCC++ +runtime_compile_setup( + TARGET ${PROJECT_NAME} + SOURCES ${RUNTIME_COMPILED_SOURCES} +) + +# 链接库 +target_link_libraries(${PROJECT_NAME} PRIVATE Drogon::Drogon) + +# 复制Swagger UI +file(COPY swagger DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) \ No newline at end of file diff --git a/cpp_server/RuntimeCompiledCPlusPlus b/cpp_server/RuntimeCompiledCPlusPlus new file mode 160000 index 0000000..a93b46d --- /dev/null +++ b/cpp_server/RuntimeCompiledCPlusPlus @@ -0,0 +1 @@ +Subproject commit a93b46d32052f16f2f0e647ef180ac92afa88764 diff --git a/cpp_server/cmake/FindRCCPP.cmake b/cpp_server/cmake/FindRCCPP.cmake new file mode 100644 index 0000000..4b58066 --- /dev/null +++ b/cpp_server/cmake/FindRCCPP.cmake @@ -0,0 +1,7 @@ +# 用于查找RCC++的头文件路径 +find_path(RCCPP_INCLUDE_DIR RuntimeObjectSystem.h + PATHS ${CMAKE_SOURCE_DIR}/RuntimeCompiledCPlusPlus/RuntimeObjectSystem +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(RCCPP DEFAULT_MSG RCCPP_INCLUDE_DIR) \ No newline at end of file diff --git a/cpp_server/src/controllers/UserController.cpp b/cpp_server/src/controllers/UserController.cpp new file mode 100644 index 0000000..ac3d1fe --- /dev/null +++ b/cpp_server/src/controllers/UserController.cpp @@ -0,0 +1,21 @@ +#include "UserController.h" + +RCCPP_RUNTIME_TYPE_REGISTRATION(UserController) + +/** + * @brief 获取用户列表 + * @route GET /api/v1/users + * @response 200 用户列表JSON + */ +void UserController::asyncHandleHttpRequest( + const drogon::HttpRequestPtr &req, + std::function &&callback) +{ + Json::Value ret; + ret["status"] = "ok"; + ret["message"] = "Hello from RCC++!"; + ret["data"] = Json::arrayValue; + + auto resp = drogon::HttpResponse::newHttpJsonResponse(ret); + callback(resp); +} \ No newline at end of file diff --git a/cpp_server/src/controllers/UserController.h b/cpp_server/src/controllers/UserController.h new file mode 100644 index 0000000..55647f1 --- /dev/null +++ b/cpp_server/src/controllers/UserController.h @@ -0,0 +1,22 @@ +#pragma once + +#include "RuntimeCompiledCPlusPlus/RuntimeObjectSystem/RuntimeObjectSystem.h" +#include + +class UserController : public RCCpp::IObject, + public drogon::HttpSimpleController +{ +public: + UserController() { RCCpp::Construct(); } + virtual ~UserController() { RCCpp::Destruct(); } + + RCCPP_RUNTIME_TYPE_DECLARATION(UserController) + + void asyncHandleHttpRequest( + const drogon::HttpRequestPtr &req, + std::function &&callback) override; + + PATH_LIST_BEGIN + PATH_ADD("/api/v1/users", drogon::Get); + PATH_LIST_END +}; \ No newline at end of file diff --git a/cpp_server/src/main.cpp b/cpp_server/src/main.cpp new file mode 100644 index 0000000..9b2b180 --- /dev/null +++ b/cpp_server/src/main.cpp @@ -0,0 +1,48 @@ +#include +#include "RuntimeCompiledCPlusPlus/RuntimeObjectSystem/RuntimeObjectSystem.h" +#include "controllers/UserController.h" + +class SystemTable : public RCCpp::ISystemTable +{ +public: + virtual void Log(RCCpp::LogSystem::LogType type, const char *pText) override + { + if (type == RCCpp::LogSystem::ERROR) + LOG_ERROR << pText; + else + LOG_INFO << pText; + } +}; + +int main() +{ + // 初始化RCC++ + SystemTable systemTable; + RCCpp::RuntimeObjectSystem runtimeObjectSystem; + runtimeObjectSystem.Initialise(&systemTable, nullptr); + + // 设置Swagger + drogon::app().registerController(std::make_shared()); + + // 加载热重载控制器 + runtimeObjectSystem.GetObjectFactorySystem()->LoadObjectFactory( + "UserController", true); + + // 设置文档路径 + drogon::app().setDocumentRoot("./swagger"); + drogon::app().setDocumentRoot("/api/v1/docs"); + + // 启动日志 + LOG_INFO << "Server running on http://127.0.0.1:8848"; + LOG_INFO << "Swagger UI: http://127.0.0.1:8848/api/v1/docs"; + LOG_INFO << "Hot reload enabled - modify controller files to see changes"; + + // 主循环 + drogon::app() + .addListener("0.0.0.0", 8848) + .setThreadNum(4) + .run(); + + runtimeObjectSystem.CleanObjectFiles(); + return 0; +} \ No newline at end of file diff --git a/documents/~$ UFT模块迁移方案.docx b/documents/~$ UFT模块迁移方案.docx deleted file mode 100644 index 1feb1b5f2f7f8b05b88b5baa6cbe27cc8333c02c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 162 dcmZR{NX^P&AQiAMWH6*MWHFGglT@1+7yz> _buildToolsMenuItems() { return [ - const PopupMenuItem(value: MenuConstants.templateParser, child: Text('XML解析')), - const PopupMenuItem(value: MenuConstants.contentSearch, child: Text('内容搜索')), - const PopupMenuItem(value: MenuConstants.dataCompare, child: Text('数据对比')), - const PopupMenuItem(value: MenuConstants.dataFormat, child: Text('数据格式化')), + const PopupMenuItem( + value: MenuConstants.templateParser, + child: ListTile(leading: Icon(Icons.auto_awesome_mosaic), title: Text('XML解析')), + ), + const PopupMenuItem( + value: MenuConstants.contentSearch, + child: ListTile(leading: Icon(Icons.search), title: Text('内容搜索')), + ), + const PopupMenuItem( + value: MenuConstants.dataCompare, + child: ListTile(leading: Icon(Icons.compare), title: Text('数据对比')), + ), + const PopupMenuItem( + value: MenuConstants.dataFormat, + child: ListTile(leading: Icon(Icons.date_range), title: Text('数据格式化')), + ), const PopupMenuDivider(), - const PopupMenuItem(value: MenuConstants.demo, child: Text('Demo')), + const PopupMenuItem( + value: MenuConstants.demo, + child: ListTile(leading: Icon(Icons.code), title: Text('Demo')), + ), + ]; + } + + List> _buildAigcMenuItems() { + return [ + const PopupMenuItem( + value: MenuConstants.uftFile, + child: ListTile(leading: Icon(Icons.drive_file_move), title: Text('UFT文件')), + ), ]; } diff --git a/win_text_editor/lib/menus/menu_actions.dart b/win_text_editor/lib/menus/menu_actions.dart index f4e7b84..83019f5 100644 --- a/win_text_editor/lib/menus/menu_actions.dart +++ b/win_text_editor/lib/menus/menu_actions.dart @@ -16,6 +16,7 @@ class MenuActions { MenuConstants.templateParser: _openTemplateParser, MenuConstants.dataFormat: _dataFormat, MenuConstants.dataCompare: _dataCompare, + MenuConstants.uftFile: _openUftFile, MenuConstants.demo: _demo, MenuConstants.exit: _exitApplication, }; @@ -47,6 +48,10 @@ class MenuActions { await _openOrActivateTab(context, "XML解析", RouterKey.templateParser, Icons.auto_awesome_mosaic); } + static Future _openUftFile(BuildContext context) async { + await _openOrActivateTab(context, "UFT文件", RouterKey.uftFile, Icons.drive_file_move); + } + static Future _dataFormat(BuildContext context) async { await _openOrActivateTab(context, "数据格式化", RouterKey.dataFormat, Icons.date_range); } diff --git a/win_text_editor/lib/menus/menu_constants.dart b/win_text_editor/lib/menus/menu_constants.dart index 6d2ff66..fa97cd3 100644 --- a/win_text_editor/lib/menus/menu_constants.dart +++ b/win_text_editor/lib/menus/menu_constants.dart @@ -19,6 +19,10 @@ class MenuConstants { static const String dataCompare = 'data_compare'; static const String demo = 'demo'; + // AIGC菜单项 + static const String aigc = 'aigc'; + static const String uftFile = 'uftFile'; + // 编辑菜单项 static const String undo = 'undo'; static const String redo = 'redo'; diff --git a/win_text_editor/lib/modules/data_compare/controllers/data_compare_controller.dart b/win_text_editor/lib/modules/data_compare/controllers/data_compare_controller.dart index a5c39ed..fdec3ef 100644 --- a/win_text_editor/lib/modules/data_compare/controllers/data_compare_controller.dart +++ b/win_text_editor/lib/modules/data_compare/controllers/data_compare_controller.dart @@ -3,7 +3,6 @@ import 'dart:io'; import 'package:file_picker/file_picker.dart'; import 'package:win_text_editor/framework/controllers/logger.dart'; import 'package:win_text_editor/shared/base/base_content_controller.dart'; -import 'package:path/path.dart' as path; class DataCompareController extends BaseContentController { List leftColumns = []; diff --git a/win_text_editor/lib/modules/demo/widgets/demo_view.dart b/win_text_editor/lib/modules/demo/widgets/demo_view.dart index 3f17a30..8f7c35e 100644 --- a/win_text_editor/lib/modules/demo/widgets/demo_view.dart +++ b/win_text_editor/lib/modules/demo/widgets/demo_view.dart @@ -42,111 +42,6 @@ class _DemoViewState extends State { @override Widget build(BuildContext context) { - return ChangeNotifierProvider.value( - value: _controller, - child: const Padding(padding: EdgeInsets.all(8.0), child: ButtonPositionExample()), - ); - } -} - -class ButtonPositionExample extends StatefulWidget { - const ButtonPositionExample({Key? key}) : super(key: key); - - @override - _ButtonPositionExampleState createState() => _ButtonPositionExampleState(); -} - -class _ButtonPositionExampleState extends State { - // 用于获取按钮位置的GlobalKey - final GlobalKey _buttonKey = GlobalKey(); - - // 存储按钮位置信息 - String _buttonPosition = '未获取'; - - // 存储点击位置信息 - String _clickPosition = '未点击'; - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: const Text('按钮位置和点击坐标示例')), - body: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - // 显示按钮位置信息 - Text('按钮位置: $_buttonPosition'), - const SizedBox(height: 10), - - // 显示点击位置信息 - Text('点击位置: $_clickPosition'), - const SizedBox(height: 30), - - // 可获取位置的按钮 - ElevatedButton( - key: _buttonKey, - onPressed: () { - _getButtonPosition(); - }, - child: const Text('获取按钮位置'), - ), - const SizedBox(height: 20), - - // 可获取点击位置的按钮 - GestureDetector( - onTapDown: (TapDownDetails details) { - _getClickPosition(details); - }, - child: Container( - padding: const EdgeInsets.all(16.0), - color: Colors.blue, - child: const Text('点击此处获取点击坐标', style: TextStyle(color: Colors.white)), - ), - ), - const SizedBox(height: 20), - - // 同时获取按钮位置和点击位置 - Builder( - builder: (BuildContext context) { - return ElevatedButton( - onPressed: () { - // 这里使用context.findRenderObject()获取当前按钮的位置 - final RenderBox renderBox = context.findRenderObject() as RenderBox; - final position = renderBox.localToGlobal(Offset.zero); - setState(() { - _buttonPosition = - '按钮位置: (${position.dx.toStringAsFixed(2)}, ${position.dy.toStringAsFixed(2)})'; - }); - }, - child: const Text('使用Builder获取按钮位置'), - ); - }, - ), - ], - ), - ), - ); - } - - // 获取按钮位置 - void _getButtonPosition() { - final RenderBox renderBox = _buttonKey.currentContext?.findRenderObject() as RenderBox; - final position = renderBox.localToGlobal(Offset.zero); - - setState(() { - _buttonPosition = - '按钮位置: (${position.dx.toStringAsFixed(2)}, ${position.dy.toStringAsFixed(2)})'; - }); - } - - // 获取点击位置 - void _getClickPosition(TapDownDetails details) { - final RenderBox renderBox = context.findRenderObject() as RenderBox; - final position = renderBox.globalToLocal(details.globalPosition); - - setState(() { - _clickPosition = - '点击位置: (${position.dx.toStringAsFixed(2)}, ${position.dy.toStringAsFixed(2)})'; - }); + return const Center(child: Text('demo')); } } diff --git a/win_text_editor/lib/modules/module_router.dart b/win_text_editor/lib/modules/module_router.dart index 38e86ec..bb0f7a7 100644 --- a/win_text_editor/lib/modules/module_router.dart +++ b/win_text_editor/lib/modules/module_router.dart @@ -7,6 +7,8 @@ import 'package:win_text_editor/modules/data_format/controllers/data_format_cont import 'package:win_text_editor/modules/data_format/widgets/data_format_view.dart'; import 'package:win_text_editor/modules/demo/controllers/demo_controller.dart'; import 'package:win_text_editor/modules/demo/widgets/demo_view.dart'; +import 'package:win_text_editor/modules/uft_file/controllers/uft_file_controller.dart'; +import 'package:win_text_editor/modules/uft_file/widgets/uft_file_view.dart'; import 'package:win_text_editor/shared/base/base_content_controller.dart'; import 'package:win_text_editor/modules/content_search/controllers/content_search_controller.dart'; import 'package:win_text_editor/modules/template_parser/controllers/template_parser_controller.dart'; @@ -19,6 +21,7 @@ class RouterKey { static const String dataFormat = 'data_format'; static const String textEditor = 'text_editor'; static const String dataCompare = 'data_compare'; + static const String uftFile = 'uft_file'; static const String demo = 'demo'; } @@ -29,6 +32,7 @@ class ModuleRouter { RouterKey.templateParser: (tab) => TemplateParserController(), RouterKey.dataFormat: (tab) => DataFormatController(), RouterKey.dataCompare: (tab) => DataCompareController(), + RouterKey.uftFile: (tab) => UftFileController(), RouterKey.demo: (tab) => DemoController(), }; @@ -38,6 +42,7 @@ class ModuleRouter { RouterKey.templateParser: (tab, controller) => TemplateParserView(tabId: tab.id), RouterKey.dataFormat: (tab, controller) => DataFormatView(tabId: tab.id), RouterKey.dataCompare: (tab, controller) => DataCompareView(tabId: tab.id), + RouterKey.uftFile: (tab, controller) => UftFileView(tabId: tab.id), RouterKey.demo: (tab, controller) => DemoView(tabId: tab.id), }; diff --git a/win_text_editor/lib/modules/uft_file/controllers/uft_file_controller.dart b/win_text_editor/lib/modules/uft_file/controllers/uft_file_controller.dart new file mode 100644 index 0000000..45bd1ec --- /dev/null +++ b/win_text_editor/lib/modules/uft_file/controllers/uft_file_controller.dart @@ -0,0 +1,13 @@ +import 'package:win_text_editor/shared/base/base_content_controller.dart'; + +class UftFileController extends BaseContentController { + @override + void onOpenFile(String filePath) { + // TODO: implement onOpenFile + } + + @override + void onOpenFolder(String folderPath) { + // TODO: implement onOpenFolder + } +} diff --git a/win_text_editor/lib/modules/uft_file/widgets/uft_file_view.dart b/win_text_editor/lib/modules/uft_file/widgets/uft_file_view.dart new file mode 100644 index 0000000..d313959 --- /dev/null +++ b/win_text_editor/lib/modules/uft_file/widgets/uft_file_view.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:win_text_editor/framework/controllers/tab_items_controller.dart'; +import 'package:win_text_editor/modules/uft_file/controllers/uft_file_controller.dart'; + +class UftFileView extends StatefulWidget { + final String tabId; + const UftFileView({super.key, required this.tabId}); + + @override + State createState() => _UftFileViewState(); +} + +class _UftFileViewState extends State { + late final UftFileController _controller; + bool _isControllerFromTabManager = false; + + get tabManager => Provider.of(context, listen: false); + + @override + void initState() { + super.initState(); + + final controllerFromManager = tabManager.getController(widget.tabId); + if (controllerFromManager != null) { + _controller = controllerFromManager; + _isControllerFromTabManager = true; + } else { + _controller = UftFileController(); + _isControllerFromTabManager = false; + tabManager.registerController(widget.tabId, _controller); + } + } + + @override + void dispose() { + if (!_isControllerFromTabManager) { + _controller.dispose(); + } + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return const Center(child: Text('demo')); + } +}