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 5337505c..31db911a 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 @@ -15,6 +15,7 @@ from .model import ( PluginSwitch, UpdatePlugin, BatchUpdatePlugins, + RenameMenuTypePayload, ) router = APIRouter(prefix="/plugin") @@ -167,3 +168,28 @@ async def batch_update_plugin_config_api(params: BatchUpdatePlugins): # raise HTTPException(status_code=400, detail={"message": "部分插件更新失败", "errors": result["errors"]}) pass # 暂时只返回结果字典 return result + + +# 新增:重命名菜单类型路由 +@router.put( + "/menu_type/rename", + dependencies=[authentication()], + response_model=Result, + summary="重命名菜单类型" +) +async def rename_menu_type_api(payload: RenameMenuTypePayload) -> Result: + try: + result = await ApiDataSource.rename_menu_type(old_name=payload.old_name, new_name=payload.new_name) + if result.get("success"): + return Result.ok(info=result.get("info", f"成功将 {result.get('updated_count', 0)} 个插件的菜单类型从 '{payload.old_name}' 修改为 '{payload.new_name}'")) + else: + # 这种情况理论上不会发生,因为 rename_menu_type 失败会抛异常 + return Result.fail(info=result.get("info", "重命名失败")) + except ValueError as ve: + return Result.fail(info=str(ve)) + except RuntimeError as re: + logger.error(f"{router.prefix}/menu_type/rename 调用错误", "WebUi", e=re) + return Result.fail(info=str(re)) + except Exception as e: + logger.error(f"{router.prefix}/menu_type/rename 调用错误", "WebUi", e=e) + return Result.fail(info=f"发生未知错误: {type(e).__name__}") diff --git a/zhenxun/builtin_plugins/web_ui/api/tabs/plugin_manage/data_source.py b/zhenxun/builtin_plugins/web_ui/api/tabs/plugin_manage/data_source.py index e7c30b62..82dd1554 100644 --- a/zhenxun/builtin_plugins/web_ui/api/tabs/plugin_manage/data_source.py +++ b/zhenxun/builtin_plugins/web_ui/api/tabs/plugin_manage/data_source.py @@ -203,6 +203,35 @@ class ApiDataSource: type_inner=type_inner, # type: ignore ) + @classmethod + async def rename_menu_type(cls, old_name: str, new_name: str) -> dict: + """重命名菜单类型,并更新所有相关插件 + + 参数: + old_name: 旧菜单类型名称 + new_name: 新菜单类型名称 + + 返回: + dict: 更新结果, 例如 {'success': True, 'updated_count': 3} + """ + if not old_name or not new_name: + raise ValueError("旧名称和新名称都不能为空") + if old_name == new_name: + return {"success": True, "updated_count": 0, "info": "新旧名称相同,无需更新"} + + # 检查新名称是否已存在(理论上前端会校验,后端再保险一次) + exists = await DbPluginInfo.filter(menu_type=new_name).exists() + if exists: + raise ValueError(f"新的菜单类型名称 '{new_name}' 已被其他插件使用") + + try: + # 使用 filter().update() 进行批量更新 + updated_count = await DbPluginInfo.filter(menu_type=old_name).update(menu_type=new_name) + return {"success": True, "updated_count": updated_count} + except Exception as e: + # 可以添加更详细的日志记录 + raise RuntimeError(f"数据库更新菜单类型失败: {str(e)}") + @classmethod async def get_plugin_detail(cls, module: str) -> PluginDetail: """获取插件详情 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 48187ad5..b943641f 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 @@ -128,6 +128,11 @@ class PluginDetail(PluginInfo): config_list: list[PluginConfig] +class RenameMenuTypePayload(BaseModel): + old_name: str = Field(..., description="旧菜单类型名称") + new_name: str = Field(..., description="新菜单类型名称") + + class PluginIr(BaseModel): id: int """插件id"""