From c766ecd9d3884b3120d7f7d9ab3a05ec244edf0b Mon Sep 17 00:00:00 2001 From: HibiKier <775757368@qq.com> Date: Fri, 20 Jun 2025 19:03:37 +0800 Subject: [PATCH] =?UTF-8?q?:bug:=20=E6=8F=92=E4=BB=B6=E5=95=86=E5=BA=97?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin_store/test_add_plugin.py | 2 +- .../plugin_store/test_search_plugin.py | 4 +- .../plugin_store/test_update_all_plugin.py | 4 +- .../plugin_store/test_update_plugin.py | 4 +- .../response/plugin_store/basic_plugins.json | 16 ++++--- .../response/plugin_store/extra_plugins.json | 10 ++-- .../plugin_store/data_source.py | 48 +++++-------------- zhenxun/utils/html_template/__init__.py | 1 + zhenxun/utils/html_template/component.py | 36 ++++++++++++++ .../utils/html_template/components/title.py | 15 ++++++ zhenxun/utils/html_template/container.py | 31 ++++++++++++ 11 files changed, 117 insertions(+), 54 deletions(-) create mode 100644 zhenxun/utils/html_template/__init__.py create mode 100644 zhenxun/utils/html_template/component.py create mode 100644 zhenxun/utils/html_template/components/title.py create mode 100644 zhenxun/utils/html_template/container.py diff --git a/tests/builtin_plugins/plugin_store/test_add_plugin.py b/tests/builtin_plugins/plugin_store/test_add_plugin.py index 3dd2ebbb..5a0edab8 100644 --- a/tests/builtin_plugins/plugin_store/test_add_plugin.py +++ b/tests/builtin_plugins/plugin_store/test_add_plugin.py @@ -359,7 +359,7 @@ async def test_add_plugin_exist( init_mocked_api(mocked_api=mocked_api) mocker.patch( - "zhenxun.builtin_plugins.plugin_store.data_source.ShopManage.get_loaded_plugins", + "zhenxun.builtin_plugins.plugin_store.data_source.StoreManager.get_loaded_plugins", return_value=[("search_image", "0.1")], ) plugin_id = 1 diff --git a/tests/builtin_plugins/plugin_store/test_search_plugin.py b/tests/builtin_plugins/plugin_store/test_search_plugin.py index 8bc6876e..404fee5e 100644 --- a/tests/builtin_plugins/plugin_store/test_search_plugin.py +++ b/tests/builtin_plugins/plugin_store/test_search_plugin.py @@ -57,7 +57,7 @@ async def test_search_plugin_name( ) ctx.receive_event(bot=bot, event=event) mock_table_page.assert_awaited_once_with( - "插件列表", + "商店插件列表", "通过添加/移除插件 ID 来管理插件", ["-", "ID", "名称", "简介", "作者", "版本", "类型"], [ @@ -123,7 +123,7 @@ async def test_search_plugin_author( ) ctx.receive_event(bot=bot, event=event) mock_table_page.assert_awaited_once_with( - "插件列表", + "商店插件列表", "通过添加/移除插件 ID 来管理插件", ["-", "ID", "名称", "简介", "作者", "版本", "类型"], [ diff --git a/tests/builtin_plugins/plugin_store/test_update_all_plugin.py b/tests/builtin_plugins/plugin_store/test_update_all_plugin.py index 2a490da7..95360f6b 100644 --- a/tests/builtin_plugins/plugin_store/test_update_all_plugin.py +++ b/tests/builtin_plugins/plugin_store/test_update_all_plugin.py @@ -32,7 +32,7 @@ async def test_update_all_plugin_basic_need_update( new=tmp_path / "zhenxun", ) mocker.patch( - "zhenxun.builtin_plugins.plugin_store.data_source.ShopManage.get_loaded_plugins", + "zhenxun.builtin_plugins.plugin_store.data_source.StoreManager.get_loaded_plugins", return_value=[("search_image", "0.0")], ) @@ -87,7 +87,7 @@ async def test_update_all_plugin_basic_is_new( new=tmp_path / "zhenxun", ) mocker.patch( - "zhenxun.builtin_plugins.plugin_store.data_source.ShopManage.get_loaded_plugins", + "zhenxun.builtin_plugins.plugin_store.data_source.StoreManager.get_loaded_plugins", return_value=[("search_image", "0.1")], ) diff --git a/tests/builtin_plugins/plugin_store/test_update_plugin.py b/tests/builtin_plugins/plugin_store/test_update_plugin.py index 952191d6..2cb88d1b 100644 --- a/tests/builtin_plugins/plugin_store/test_update_plugin.py +++ b/tests/builtin_plugins/plugin_store/test_update_plugin.py @@ -32,7 +32,7 @@ async def test_update_plugin_basic_need_update( new=tmp_path / "zhenxun", ) mocker.patch( - "zhenxun.builtin_plugins.plugin_store.data_source.ShopManage.get_loaded_plugins", + "zhenxun.builtin_plugins.plugin_store.data_source.StoreManager.get_loaded_plugins", return_value=[("search_image", "0.0")], ) @@ -87,7 +87,7 @@ async def test_update_plugin_basic_is_new( new=tmp_path / "zhenxun", ) mocker.patch( - "zhenxun.builtin_plugins.plugin_store.data_source.ShopManage.get_loaded_plugins", + "zhenxun.builtin_plugins.plugin_store.data_source.StoreManager.get_loaded_plugins", return_value=[("search_image", "0.1")], ) diff --git a/tests/response/plugin_store/basic_plugins.json b/tests/response/plugin_store/basic_plugins.json index 7459e2ec..f0306836 100644 --- a/tests/response/plugin_store/basic_plugins.json +++ b/tests/response/plugin_store/basic_plugins.json @@ -1,5 +1,6 @@ -{ - "鸡汤": { +[ + { + "name": "鸡汤", "module": "jitang", "module_path": "plugins.alapi.jitang", "description": "喏,亲手为你煮的鸡汤", @@ -9,7 +10,8 @@ "plugin_type": "NORMAL", "is_dir": false }, - "识图": { + { + "name": "识图", "module": "search_image", "module_path": "plugins.search_image", "description": "以图搜图,看破本源", @@ -19,7 +21,8 @@ "plugin_type": "NORMAL", "is_dir": true }, - "网易云热评": { + { + "name": "网易云热评", "module": "comments_163", "module_path": "plugins.alapi.comments_163", "description": "生了个人,我很抱歉", @@ -29,7 +32,8 @@ "plugin_type": "NORMAL", "is_dir": false }, - "B站订阅": { + { + "name": "B站订阅", "module": "bilibili_sub", "module_path": "plugins.bilibili_sub", "description": "非常便利的B站订阅通知", @@ -39,4 +43,4 @@ "plugin_type": "NORMAL", "is_dir": true } -} +] diff --git a/tests/response/plugin_store/extra_plugins.json b/tests/response/plugin_store/extra_plugins.json index 9d92f859..ca5e7f0a 100644 --- a/tests/response/plugin_store/extra_plugins.json +++ b/tests/response/plugin_store/extra_plugins.json @@ -1,5 +1,6 @@ -{ - "github订阅": { +[ + { + "name": "github订阅", "module": "github_sub", "module_path": "github_sub", "description": "订阅github用户或仓库", @@ -10,7 +11,8 @@ "is_dir": true, "github_url": "https://github.com/xuanerwa/zhenxun_github_sub" }, - "Minecraft查服": { + { + "name": "Minecraft查服", "module": "mc_check", "module_path": "mc_check", "description": "Minecraft服务器状态查询,支持IPv6", @@ -21,4 +23,4 @@ "is_dir": true, "github_url": "https://github.com/molanp/zhenxun_check_Minecraft" } -} +] diff --git a/zhenxun/builtin_plugins/plugin_store/data_source.py b/zhenxun/builtin_plugins/plugin_store/data_source.py index 9ca85e3d..6633d404 100644 --- a/zhenxun/builtin_plugins/plugin_store/data_source.py +++ b/zhenxun/builtin_plugins/plugin_store/data_source.py @@ -55,32 +55,6 @@ def install_requirement(plugin_path: Path): ): VirtualEnvPackageManager.install_requirement(existing_requirements) - if not existing_requirements: - logger.debug( - f"No requirement.txt found for plugin: {plugin_path.name}", "插件管理" - ) - return - - try: - command = WIN_COMMAND if BAT_FILE.exists() else DEFAULT_COMMAND - command.append(str(existing_requirements)) - result = subprocess.run( - command, - check=True, - capture_output=True, - text=True, - ) - logger.debug( - "Successfully installed dependencies for" - f" plugin: {plugin_path.name}. Output:\n{result.stdout}", - "插件管理", - ) - except subprocess.CalledProcessError: - logger.error( - f"Failed to install dependencies for plugin: {plugin_path.name}. " - " Error:\n{e.stderr}" - ) - class StoreManager: @classmethod @@ -232,7 +206,7 @@ class StoreManager: db_plugin_list = await cls.get_loaded_plugins("module") plugin_info = next(p for p in plugin_list if p.module == plugin_key) if plugin_info.module in [p[0] for p in db_plugin_list]: - return f"插件 {plugin_key} 已安装,无需重复安装" + return f"插件 {plugin_info.name} 已安装,无需重复安装" is_external = True if plugin_info.github_url is None: plugin_info.github_url = DEFAULT_GITHUB_URL @@ -241,14 +215,14 @@ class StoreManager: if len(version_split) > 1: github_url_split = plugin_info.github_url.split("/tree/") plugin_info.github_url = f"{github_url_split[0]}/tree/{version_split[1]}" - logger.info(f"正在安装插件 {plugin_key}...", LOG_COMMAND) + logger.info(f"正在安装插件 {plugin_info.name}...", LOG_COMMAND) await cls.install_plugin_with_repo( plugin_info.github_url, plugin_info.module_path, plugin_info.is_dir, is_external, ) - return f"插件 {plugin_key} 安装成功! 重启后生效" + return f"插件 {plugin_info.name} 安装成功! 重启后生效" @classmethod async def install_plugin_with_repo( @@ -348,14 +322,14 @@ class StoreManager: if not plugin_info.is_dir: path = Path(f"{path}.py") if not path.exists(): - return f"插件 {plugin_key} 不存在..." - logger.debug(f"尝试移除插件 {plugin_key} 文件: {path}", LOG_COMMAND) + return f"插件 {plugin_info.name} 不存在..." + logger.debug(f"尝试移除插件 {plugin_info.name} 文件: {path}", LOG_COMMAND) if plugin_info.is_dir: shutil.rmtree(path) else: path.unlink() await PluginInitManager.remove(f"zhenxun.{plugin_info.module_path}") - return f"插件 {plugin_key} 移除成功! 重启后生效" + return f"插件 {plugin_info.name} 移除成功! 重启后生效" @classmethod async def search_plugin(cls, plugin_name_or_author: str) -> BuildImage | str: @@ -393,7 +367,7 @@ class StoreManager: return "未找到相关插件..." column_name = ["-", "ID", "名称", "简介", "作者", "版本", "类型"] return await ImageTemplate.table_page( - "商店列表", + "商店插件列表", "通过添加/移除插件 ID 来管理插件", column_name, data_list, @@ -415,15 +389,15 @@ class StoreManager: plugin_key = await cls._resolve_plugin_key(plugin_id) except ValueError as e: return str(e) - logger.info(f"尝试更新插件 {plugin_key}", LOG_COMMAND) plugin_info = next(p for p in plugin_list if p.module == plugin_key) + logger.info(f"尝试更新插件 {plugin_info.name}", LOG_COMMAND) db_plugin_list = await cls.get_loaded_plugins("module", "version") suc_plugin = {p[0]: (p[1] or "Unknown") for p in db_plugin_list} if plugin_info.module not in [p[0] for p in db_plugin_list]: - return f"插件 {plugin_key} 未安装,无法更新" + return f"插件 {plugin_info.name} 未安装,无法更新" logger.debug(f"当前插件列表: {suc_plugin}", LOG_COMMAND) if cls.check_version_is_new(plugin_info, suc_plugin): - return f"插件 {plugin_key} 已是最新版本" + return f"插件 {plugin_info.name} 已是最新版本" is_external = True if plugin_info.github_url is None: plugin_info.github_url = DEFAULT_GITHUB_URL @@ -434,7 +408,7 @@ class StoreManager: plugin_info.is_dir, is_external, ) - return f"插件 {plugin_key} 更新成功! 重启后生效" + return f"插件 {plugin_info.name} 更新成功! 重启后生效" @classmethod async def update_all_plugin(cls) -> str: diff --git a/zhenxun/utils/html_template/__init__.py b/zhenxun/utils/html_template/__init__.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/zhenxun/utils/html_template/__init__.py @@ -0,0 +1 @@ + diff --git a/zhenxun/utils/html_template/component.py b/zhenxun/utils/html_template/component.py new file mode 100644 index 00000000..c23ed503 --- /dev/null +++ b/zhenxun/utils/html_template/component.py @@ -0,0 +1,36 @@ +from abc import ABC +from typing import Literal + +from pydantic import BaseModel + + +class Style(BaseModel): + """常用样式""" + + padding: str = "0px" + margin: str = "0px" + border: str = "0px" + border_radius: str = "0px" + text_align: Literal["left", "right", "center"] = "left" + color: str = "#000" + font_size: str = "16px" + + +class Component(ABC): + def __init__(self, background_color: str = "#fff", is_container: bool = False): + self.extra_style = [] + self.style = Style() + self.background_color = background_color + self.is_container = is_container + self.children = [] + + def add_child(self, child: "Component | str"): + self.children.append(child) + + def set_style(self, style: Style): + self.style = style + + def add_style(self, style: str): + self.extra_style.append(style) + + def to_html(self) -> str: ... diff --git a/zhenxun/utils/html_template/components/title.py b/zhenxun/utils/html_template/components/title.py new file mode 100644 index 00000000..860ad17e --- /dev/null +++ b/zhenxun/utils/html_template/components/title.py @@ -0,0 +1,15 @@ +from ..component import Component, Style +from ..container import Row + + +class Title(Component): + def __init__(self, text: str, color: str = "#000"): + self.text = text + self.color = color + + def build(self): + row = Row() + style = Style(font_size="36px", color=self.color) + row.set_style(style) + + # def diff --git a/zhenxun/utils/html_template/container.py b/zhenxun/utils/html_template/container.py new file mode 100644 index 00000000..3d5341c0 --- /dev/null +++ b/zhenxun/utils/html_template/container.py @@ -0,0 +1,31 @@ +from .component import Component + + +class Row(Component): + def __init__(self, background_color: str = "#fff"): + super().__init__(background_color, True) + + +class Col(Component): + def __init__(self, background_color: str = "#fff"): + super().__init__(background_color, True) + + +class Container(Component): + def __init__(self, background_color: str = "#fff"): + super().__init__(background_color, True) + self.children = [] + + +class GlobalOverview: + def __init__(self, name: str): + self.name = name + self.class_name: dict[str, list[str]] = {} + self.content = None + + def set_content(self, content: Container): + self.content = content + + def add_class(self, class_name: str, contents: list[str]): + """全局样式""" + self.class_name[class_name] = contents