From dc6290622b12f3f6bc7049adea19caf06500b39c Mon Sep 17 00:00:00 2001 From: smock Date: Fri, 13 Feb 2026 10:31:41 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E9=9D=9E=E8=B4=9F=E6=95=B0=E7=BB=93?= =?UTF-8?q?=E6=9E=9C=E7=9A=84=E9=AA=8C=E8=AF=81=E7=A0=81=E6=9B=B4=E5=8F=8B?= =?UTF-8?q?=E5=A5=BD=E4=B8=80=E4=BA=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-fastapi-backend/module_admin/service/captcha_service.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ruoyi-fastapi-backend/module_admin/service/captcha_service.py b/ruoyi-fastapi-backend/module_admin/service/captcha_service.py index b90caa0d3..7a8126997 100644 --- a/ruoyi-fastapi-backend/module_admin/service/captcha_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/captcha_service.py @@ -34,6 +34,10 @@ async def create_captcha_image_service(cls) -> list[str, int]: result = num1 + num2 elif operational_character == '-': result = num1 - num2 + # 非负数结果的验证码更友好一些 + if result < 0: + num1, num2 = num2, num1 + result = num1 - num2 else: result = num1 * num2 # 绘制文本 From 9d3eb667414add16006038d08df8ded79e75debb Mon Sep 17 00:00:00 2001 From: smock Date: Fri, 13 Feb 2026 10:42:58 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=89=8B=E5=8A=A8?= =?UTF-8?q?=E5=AF=BC=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/common/router.py | 40 +++++++++++++++++++++++++- 2 files changed, 40 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/common/router.py b/ruoyi-fastapi-backend/common/router.py index f7106c5f9..2f6f8470f 100644 --- a/ruoyi-fastapi-backend/common/router.py +++ b/ruoyi-fastapi-backend/common/router.py @@ -308,7 +308,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 +352,10 @@ def _import_module_and_get_routers(self, controller_files: list[str]) -> list[tu :return: 路由实例列表 """ 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) From 93d48d9d989b3aae8fa8e93327c458dc8a734001 Mon Sep 17 00:00:00 2001 From: smock Date: Fri, 13 Feb 2026 10:58:52 +0800 Subject: [PATCH 3/3] =?UTF-8?q?Revert=20"=E5=A2=9E=E5=8A=A0=E6=89=8B?= =?UTF-8?q?=E5=8A=A8=E5=AF=BC=E5=85=A5=E8=B7=AF=E7=94=B1=E3=80=81fix=20bug?= =?UTF-8?q?"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 9d3eb667414add16006038d08df8ded79e75debb. --- .gitignore | 2 +- ruoyi-fastapi-backend/common/router.py | 40 +------------------------- 2 files changed, 2 insertions(+), 40 deletions(-) diff --git a/.gitignore b/.gitignore index 70cb8f1d1..220a6961d 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/common/router.py b/ruoyi-fastapi-backend/common/router.py index 2f6f8470f..f7106c5f9 100644 --- a/ruoyi-fastapi-backend/common/router.py +++ b/ruoyi-fastapi-backend/common/router.py @@ -308,41 +308,7 @@ def _find_controller_files(self) -> list[str]: :return: py文件路径列表 """ pattern = os.path.join(self.project_root, '*', 'controller', '[!_]*.py') - 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 + return sorted(glob.glob(pattern)) def _import_module_and_get_routers(self, controller_files: list[str]) -> list[tuple[str, APIRouter]]: """ @@ -352,10 +318,6 @@ def _import_module_and_get_routers(self, controller_files: list[str]) -> list[tu :return: 路由实例列表 """ 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)