diff --git a/zhenxun/builtin_plugins/web_ui/api/tabs/plugin_manage/__init__.py b/zhenxun/builtin_plugins/web_ui/api/tabs/plugin_manage/__init__.py index 9dd134a4..1187ad65 100644 --- a/zhenxun/builtin_plugins/web_ui/api/tabs/plugin_manage/__init__.py +++ b/zhenxun/builtin_plugins/web_ui/api/tabs/plugin_manage/__init__.py @@ -4,6 +4,7 @@ from fastapi.responses import JSONResponse from zhenxun.models.plugin_info import PluginInfo as DbPluginInfo from zhenxun.services.log import logger from zhenxun.utils.enum import BlockType, PluginType +from zhenxun.utils.manager.virtual_env_package_manager import VirtualEnvPackageManager from ....base_model import Result from ....utils import authentication, clear_help_image @@ -11,6 +12,7 @@ from .data_source import ApiDataSource from .model import ( BatchUpdatePlugins, BatchUpdateResult, + InstallDependenciesPayload, PluginCount, PluginDetail, PluginInfo, @@ -162,9 +164,9 @@ async def _(module: str) -> Result[PluginDetail]: dependencies=[authentication()], response_model=Result[BatchUpdateResult], response_class=JSONResponse, - summary="批量更新插件配置", + description="批量更新插件配置", ) -async def batch_update_plugin_config_api( +async def _( params: BatchUpdatePlugins, ) -> Result[BatchUpdateResult]: """批量更新插件配置,如开关、类型等""" @@ -187,9 +189,9 @@ async def batch_update_plugin_config_api( "/menu_type/rename", dependencies=[authentication()], response_model=Result, - summary="重命名菜单类型", + description="重命名菜单类型", ) -async def rename_menu_type_api(payload: RenameMenuTypePayload) -> Result: +async def _(payload: RenameMenuTypePayload) -> Result[str]: try: result = await ApiDataSource.rename_menu_type( old_name=payload.old_name, new_name=payload.new_name @@ -213,3 +215,24 @@ async def rename_menu_type_api(payload: RenameMenuTypePayload) -> Result: except Exception as e: logger.error(f"{router.prefix}/menu_type/rename 调用错误", "WebUi", e=e) return Result.fail(info=f"发生未知错误: {type(e).__name__}") + + +@router.post( + "/install_dependencies", + dependencies=[authentication()], + response_model=Result, + response_class=JSONResponse, + description="安装/卸载依赖", +) +async def _(payload: InstallDependenciesPayload) -> Result: + try: + if not payload.dependencies: + return Result.fail("依赖列表不能为空") + if payload.handle_type == "install": + result = VirtualEnvPackageManager.install(payload.dependencies) + else: + result = VirtualEnvPackageManager.uninstall(payload.dependencies) + return Result.ok(result) + except Exception as e: + logger.error(f"{router.prefix}/install_dependencies 调用错误", "WebUi", e=e) + return Result.fail(f"发生了一点错误捏 {type(e)}: {e}") diff --git a/zhenxun/builtin_plugins/web_ui/api/tabs/plugin_manage/model.py b/zhenxun/builtin_plugins/web_ui/api/tabs/plugin_manage/model.py index 579f3104..007e55e0 100644 --- a/zhenxun/builtin_plugins/web_ui/api/tabs/plugin_manage/model.py +++ b/zhenxun/builtin_plugins/web_ui/api/tabs/plugin_manage/model.py @@ -1,4 +1,4 @@ -from typing import Any +from typing import Any, Literal from pydantic import BaseModel, Field @@ -162,3 +162,15 @@ class BatchUpdateResult(BaseModel): default_factory=list, description="错误信息列表" ) """错误信息列表""" + + +class InstallDependenciesPayload(BaseModel): + """ + 安装依赖 + """ + + handle_type: Literal["install", "uninstall"] = Field(..., description="处理类型") + """处理类型""" + + dependencies: list[str] = Field(..., description="依赖列表") + """依赖列表""" diff --git a/zhenxun/utils/manager/virtual_env_package_manager.py b/zhenxun/utils/manager/virtual_env_package_manager.py index c4665bd5..ba60d9b3 100644 --- a/zhenxun/utils/manager/virtual_env_package_manager.py +++ b/zhenxun/utils/manager/virtual_env_package_manager.py @@ -31,7 +31,9 @@ class VirtualEnvPackageManager: def __get_command(cls) -> list[str]: if path := Config.get_config("virtualenv", "python_path"): return [path, "-m", "pip"] - return cls.WIN_COMMAND if BAT_FILE.exists() else cls.DEFAULT_COMMAND + return ( + cls.WIN_COMMAND.copy() if BAT_FILE.exists() else cls.DEFAULT_COMMAND.copy() + ) @classmethod def install(cls, package: list[str] | str): @@ -57,8 +59,10 @@ class VirtualEnvPackageManager: f"安装虚拟环境包指令执行完成: {result.stdout}", LOG_COMMAND, ) + return result.stdout except CalledProcessError as e: logger.error(f"安装虚拟环境包指令执行失败: {e.stderr}.", LOG_COMMAND) + return e.stderr @classmethod def uninstall(cls, package: list[str] | str): @@ -72,6 +76,7 @@ class VirtualEnvPackageManager: try: command = cls.__get_command() command.append("uninstall") + command.append("-y") command.append(" ".join(package)) logger.info(f"执行虚拟环境卸载包指令: {command}", LOG_COMMAND) result = subprocess.run( @@ -84,8 +89,10 @@ class VirtualEnvPackageManager: f"卸载虚拟环境包指令执行完成: {result.stdout}", LOG_COMMAND, ) + return result.stdout except CalledProcessError as e: logger.error(f"卸载虚拟环境包指令执行失败: {e.stderr}.", LOG_COMMAND) + return e.stderr @classmethod def update(cls, package: list[str] | str): @@ -109,8 +116,10 @@ class VirtualEnvPackageManager: text=True, ) logger.debug(f"更新虚拟环境包指令执行完成: {result.stdout}", LOG_COMMAND) + return result.stdout except CalledProcessError as e: logger.error(f"更新虚拟环境包指令执行失败: {e.stderr}.", LOG_COMMAND) + return e.stderr @classmethod def install_requirement(cls, requirement_file: Path): @@ -140,11 +149,13 @@ class VirtualEnvPackageManager: f"安装虚拟环境依赖文件指令执行完成: {result.stdout}", LOG_COMMAND, ) + return result.stdout except CalledProcessError as e: logger.error( f"安装虚拟环境依赖文件指令执行失败: {e.stderr}.", LOG_COMMAND, ) + return e.stderr @classmethod def list(cls) -> str: