From 0b87b32480ec7de550a05a045762a0dda05f9c3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A2=A8=E6=A2=93=E6=9F=92?= <1787882683@qq.com> Date: Sun, 14 Dec 2025 01:06:38 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=8F=92=E4=BB=B6=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E6=96=87=E6=A1=A3=E5=92=8C=E9=85=8D=E7=BD=AE=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugin_system/__init__.py | 6 ++++ src/plugin_system/base/__init__.py | 5 ++- src/plugin_system/base/config_types.py | 10 ++++++ src/webui/plugin_routes.py | 42 ++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/plugin_system/__init__.py b/src/plugin_system/__init__.py index a3561f0e..7e92a60d 100644 --- a/src/plugin_system/__init__.py +++ b/src/plugin_system/__init__.py @@ -11,6 +11,9 @@ from .base import ( BaseCommand, BaseTool, ConfigField, + ConfigSection, + ConfigLayout, + ConfigTab, ComponentType, ActionActivationType, ChatMode, @@ -116,6 +119,9 @@ __all__ = [ # 装饰器 "register_plugin", "ConfigField", + "ConfigSection", + "ConfigLayout", + "ConfigTab", # 工具函数 "ManifestValidator", "get_logger", diff --git a/src/plugin_system/base/__init__.py b/src/plugin_system/base/__init__.py index a8c320bf..9f930b5a 100644 --- a/src/plugin_system/base/__init__.py +++ b/src/plugin_system/base/__init__.py @@ -29,7 +29,7 @@ from .component_types import ( ForwardNode, ReplySetModel, ) -from .config_types import ConfigField +from .config_types import ConfigField, ConfigSection, ConfigLayout, ConfigTab __all__ = [ "BasePlugin", @@ -46,6 +46,9 @@ __all__ = [ "PluginInfo", "PythonDependency", "ConfigField", + "ConfigSection", + "ConfigLayout", + "ConfigTab", "EventHandlerInfo", "EventType", "BaseEventHandler", diff --git a/src/plugin_system/base/config_types.py b/src/plugin_system/base/config_types.py index c8537ace..18a98614 100644 --- a/src/plugin_system/base/config_types.py +++ b/src/plugin_system/base/config_types.py @@ -70,6 +70,12 @@ class ConfigField: depends_on: Optional[str] = None # 依赖的字段路径,如 "section.field" depends_value: Any = None # 依赖字段需要的值(当依赖字段等于此值时显示) + # === 列表类型专用 === + item_type: Optional[str] = None # 数组元素类型: "string", "number", "object" + item_fields: Optional[Dict[str, Any]] = None # 当 item_type="object" 时,定义对象的字段结构 + min_items: Optional[int] = None # 数组最小元素数量 + max_items: Optional[int] = None # 数组最大元素数量 + def get_ui_type(self) -> str: """ 获取 UI 控件类型 @@ -132,6 +138,10 @@ class ConfigField: "group": self.group, "depends_on": self.depends_on, "depends_value": self.depends_value, + "item_type": self.item_type, + "item_fields": self.item_fields, + "min_items": self.min_items, + "max_items": self.max_items, } diff --git a/src/webui/plugin_routes.py b/src/webui/plugin_routes.py index 00c960d3..2e757aac 100644 --- a/src/webui/plugin_routes.py +++ b/src/webui/plugin_routes.py @@ -1401,12 +1401,34 @@ async def get_plugin_config_schema( # 推断字段类型 field_type = type(field_value).__name__ ui_type = "text" + item_type = None + item_fields = None + if isinstance(field_value, bool): ui_type = "switch" elif isinstance(field_value, (int, float)): ui_type = "number" elif isinstance(field_value, list): ui_type = "list" + # 推断数组元素类型 + if field_value: + first_item = field_value[0] + if isinstance(first_item, dict): + item_type = "object" + # 从第一个元素推断字段结构 + item_fields = {} + for k, v in first_item.items(): + item_fields[k] = { + "type": "number" if isinstance(v, (int, float)) else "string", + "label": k, + "default": "" if isinstance(v, str) else 0, + } + elif isinstance(first_item, (int, float)): + item_type = "number" + else: + item_type = "string" + else: + item_type = "string" elif isinstance(field_value, dict): ui_type = "json" @@ -1421,6 +1443,26 @@ async def get_plugin_config_schema( "hidden": False, "disabled": False, "order": 0, + "item_type": item_type, + "item_fields": item_fields, + "min_items": None, + "max_items": None, + # 补充缺失的字段 + "placeholder": None, + "hint": None, + "icon": None, + "example": None, + "choices": None, + "min": None, + "max": None, + "step": None, + "pattern": None, + "max_length": None, + "input_type": None, + "rows": 3, + "group": None, + "depends_on": None, + "depends_value": None, } return {"success": True, "schema": schema}