From bb4b4357d4028b00d75b4552e4b613b8efb7e182 Mon Sep 17 00:00:00 2001 From: smock Date: Fri, 13 Feb 2026 12:15:29 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=89=8B=E5=8A=A8=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E8=B7=AF=E7=94=B1=E3=80=81fix=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- ruoyi-fastapi-backend/.env.dev | 2 ++ ruoyi-fastapi-backend/.env.dockermy | 2 ++ ruoyi-fastapi-backend/.env.dockerpg | 2 ++ ruoyi-fastapi-backend/.env.prod | 2 ++ ruoyi-fastapi-backend/common/router.py | 43 +++++++++++++++++++++++++- ruoyi-fastapi-backend/config/env.py | 1 + 7 files changed, 52 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 220a6961d..70cb8f1d1 100644 --- a/.gitignore +++ b/.gitignore @@ -85,7 +85,7 @@ ipython_config.py # pyenv # For a library or package, you might want to ignore these files since the code is # intended to run in multiple environments; otherwise, check them in: -# .python-version +.python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. diff --git a/ruoyi-fastapi-backend/.env.dev b/ruoyi-fastapi-backend/.env.dev index 0f22dfe18..98d8429a5 100644 --- a/ruoyi-fastapi-backend/.env.dev +++ b/ruoyi-fastapi-backend/.env.dev @@ -25,6 +25,8 @@ APP_DEMO_MODE = false APP_DISABLE_SWAGGER = false # 应用是否禁用ReDoc文档 APP_DISABLE_REDOC = false +# 应用是否启用手动导入路由(默认为自动扫描routers目录) +APP_MANUAL_IMPORT_ROUTERS = false # -------- Jwt配置 -------- # Jwt秘钥 diff --git a/ruoyi-fastapi-backend/.env.dockermy b/ruoyi-fastapi-backend/.env.dockermy index 85f1d280e..0c4ec8adc 100644 --- a/ruoyi-fastapi-backend/.env.dockermy +++ b/ruoyi-fastapi-backend/.env.dockermy @@ -25,6 +25,8 @@ APP_DEMO_MODE = false APP_DISABLE_SWAGGER = true # 应用是否禁用ReDoc文档 APP_DISABLE_REDOC = true +# 应用是否启用手动导入路由(默认为自动扫描routers目录) +APP_MANUAL_IMPORT_ROUTERS = false # -------- Jwt配置 -------- # Jwt秘钥 diff --git a/ruoyi-fastapi-backend/.env.dockerpg b/ruoyi-fastapi-backend/.env.dockerpg index 5d531545e..19f8d7a00 100644 --- a/ruoyi-fastapi-backend/.env.dockerpg +++ b/ruoyi-fastapi-backend/.env.dockerpg @@ -25,6 +25,8 @@ APP_SAME_TIME_LOGIN = true APP_DISABLE_SWAGGER = true # 应用是否禁用ReDoc文档 APP_DISABLE_REDOC = true +# 应用是否启用手动导入路由(默认为自动扫描routers目录) +APP_MANUAL_IMPORT_ROUTERS = false # -------- Jwt配置 -------- # Jwt秘钥 diff --git a/ruoyi-fastapi-backend/.env.prod b/ruoyi-fastapi-backend/.env.prod index 9d1bf5ba5..04266f186 100644 --- a/ruoyi-fastapi-backend/.env.prod +++ b/ruoyi-fastapi-backend/.env.prod @@ -25,6 +25,8 @@ APP_DEMO_MODE = false APP_DISABLE_SWAGGER = true # 应用是否禁用ReDoc文档 APP_DISABLE_REDOC = true +# 应用是否启用手动导入路由(默认为自动扫描routers目录) +APP_MANUAL_IMPORT_ROUTERS = false # -------- Jwt配置 -------- # Jwt秘钥 diff --git a/ruoyi-fastapi-backend/common/router.py b/ruoyi-fastapi-backend/common/router.py index f7106c5f9..064443353 100644 --- a/ruoyi-fastapi-backend/common/router.py +++ b/ruoyi-fastapi-backend/common/router.py @@ -16,6 +16,8 @@ from starlette.types import ASGIApp, Lifespan from typing_extensions import deprecated +from config.env import AppConfig + class APIRouterPro(APIRouter): """ @@ -308,7 +310,41 @@ def _find_controller_files(self) -> list[str]: :return: py文件路径列表 """ pattern = os.path.join(self.project_root, '*', 'controller', '[!_]*.py') - return sorted(glob.glob(pattern)) + files = glob.glob(pattern) + # 去重并保持顺序 VSCode 调试模式 + Uvicorn 热重载 环境下,可能返回重复的文件路径。 :os.path.join(self.project_root, '*', 'controller', '[!_]*.py') 中的 * 可能匹配到符号链接指向的同一物理目录,导致同一个文件通过不同路径(真实路径 vs 链接路径)被重复匹配。 + return sorted(dict.fromkeys(files)) + + def _exclude_controller_file_and_manual_import_routers( + self, all_file_names: list[str] + ) -> tuple[list[str], list[tuple[str, APIRouter]]]: + """ + 排除指定的controller文件,并手动导入路由实例(性能比较烂的朋友在debug+reload的时候可以快一点) + + :param file_name: 要排除的controller文件名 + :return: 路由实例列表 + """ + exclude_file_names = [ + 'ai_chat_controller.py', + 'ai_model_controller.py', + ] + + if not exclude_file_names: + return all_file_names, [] + + all_file_names_exclude = [] # 过滤后的文件名列表 + all_file_names_exclude = [ + fname for fname in all_file_names if not any(exclude in fname for exclude in exclude_file_names) + ] + + routers = [] + # 手动导入路由实例 + from module_ai.controller import ai_chat_controller, ai_model_controller # noqa: PLC0415 + + # 这个文件太大了,电脑性能很差的用户动态导入会很久5s+ + routers.append(('module_ai.controller.ai_chat_controller', ai_chat_controller.ai_chat_controller)) + routers.append(('module_ai.controller.ai_model_controller', ai_model_controller.ai_model_controller)) + + return all_file_names_exclude, routers def _import_module_and_get_routers(self, controller_files: list[str]) -> list[tuple[str, APIRouter]]: """ @@ -318,6 +354,11 @@ def _import_module_and_get_routers(self, controller_files: list[str]) -> list[tu :return: 路由实例列表 """ routers = [] + + if AppConfig.app_manual_import_routers: + controller_files, manual_routers = self._exclude_controller_file_and_manual_import_routers(controller_files) + routers.extend(manual_routers) + for file_path in controller_files: # 计算模块路径 relative_path = os.path.relpath(file_path, self.project_root) diff --git a/ruoyi-fastapi-backend/config/env.py b/ruoyi-fastapi-backend/config/env.py index 89baec580..d1d961ab6 100644 --- a/ruoyi-fastapi-backend/config/env.py +++ b/ruoyi-fastapi-backend/config/env.py @@ -27,6 +27,7 @@ class AppSettings(BaseSettings): app_demo_mode: bool = False app_disable_swagger: bool = False app_disable_redoc: bool = False + app_manual_import_routers: bool = False class JwtSettings(BaseSettings):