From 9a52eb33bf9a0adefb190d77d036b5a6adade9e5 Mon Sep 17 00:00:00 2001 From: liuwei Date: Thu, 30 Apr 2026 17:51:45 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=90=8E=E5=8F=B0=E5=91=BD?= =?UTF-8?q?=E4=BB=A4=E7=B4=A2=E5=BC=95=E9=A1=B5=E9=9D=A2=E4=B8=8E=E7=BE=A4?= =?UTF-8?q?=E5=91=BD=E4=BB=A4=E8=A7=86=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin/dashboard/blueprints/plugin_routes.py | 69 +++ admin/dashboard/templates/base.html | 2 + .../dashboard/templates/command_catalog.html | 478 ++++++++++++++++++ docs/工程优化与Feature清单.md | 3 +- plugins/robot_menu/menu_render_tool.py | 15 +- 5 files changed, 562 insertions(+), 5 deletions(-) create mode 100644 admin/dashboard/templates/command_catalog.html diff --git a/admin/dashboard/blueprints/plugin_routes.py b/admin/dashboard/blueprints/plugin_routes.py index 682fceb..40d3dde 100644 --- a/admin/dashboard/blueprints/plugin_routes.py +++ b/admin/dashboard/blueprints/plugin_routes.py @@ -7,11 +7,42 @@ from flask import Blueprint, request, jsonify, render_template, current_app from admin.dashboard.blueprints.auth import login_required from utils.robot_cmd.robot_command import GroupBotManager, PermissionStatus +from plugins.robot_menu.menu_render_tool import RobotMenuRenderTool # 创建蓝图 plugin_routes = Blueprint('plugin_routes', __name__) LOG = logger +# 后台命令索引页只复用“命令目录生成”能力,不需要图片渲染, +# 因此这里固定使用轻量 text 配置创建一个工具实例即可。 +_command_catalog_tool = RobotMenuRenderTool( + output_mode="text", + image_fallback_to_text=True, + image_render_timeout_seconds=30, + image_render_retries=1, + image_template_path="plugins/robot_menu/templates/menu_cards.html", + log=LOG, +) + + +def _build_group_options(server) -> list: + """构建后台命令索引页的群组选项列表。""" + group_ids = sorted(set(GroupBotManager.get_group_list() or [])) + options = [] + for group_id in group_ids: + group_name = "" + try: + group_name = server.contact_manager.get_nickname(group_id) or "" + except Exception: + group_name = "" + options.append( + { + "group_id": group_id, + "group_name": str(group_name or group_id), + } + ) + return options + # 机器人管理页面 @plugin_routes.route('/plugins_manage') @@ -20,6 +51,13 @@ def robot_management(): return render_template('plugins_manage.html') +@plugin_routes.route('/command_catalog') +@login_required +def command_catalog_page(): + """后台命令索引页面。""" + return render_template('command_catalog.html') + + @plugin_routes.route('/api/plugins', methods=['GET']) @login_required def get_plugins(): @@ -37,6 +75,37 @@ def get_plugins(): return jsonify({"success": False, "message": f"获取插件列表失败: {str(e)}"}) +@plugin_routes.route('/api/plugins/command_catalog', methods=['GET']) +@login_required +def get_command_catalog(): + """获取后台命令索引数据。""" + try: + server = current_app.dashboard_server + group_id = str(request.args.get('group_id') or '').strip() + + # 后台命令索引默认站在“管理员”视角, + # 这样既能看到当前可用命令,也能看到未启用能力和管理指令。 + catalog = _command_catalog_tool.build_command_catalog_data( + group_id=group_id, + requester_id="dashboard_admin", + force_admin=True, + ) + data = { + **catalog, + "group_options": _build_group_options(server), + "summary": { + "available_manual_count": len(catalog.get("available_manual", []) or []), + "available_auto_count": len(catalog.get("available_auto", []) or []), + "unavailable_manual_count": len(catalog.get("unavailable_manual", []) or []), + "admin_command_count": len(catalog.get("admin_commands", []) or []), + }, + } + return jsonify({"success": True, "data": data}) + except Exception as e: + LOG.error(f"获取命令索引失败: {str(e)}", exc_info=True) + return jsonify({"success": False, "message": f"获取命令索引失败: {str(e)}"}) + + @plugin_routes.route('/api/plugins/group_status', methods=['GET']) @login_required def get_plugin_group_status(): diff --git a/admin/dashboard/templates/base.html b/admin/dashboard/templates/base.html index eca0f07..84133bc 100644 --- a/admin/dashboard/templates/base.html +++ b/admin/dashboard/templates/base.html @@ -1012,6 +1012,7 @@ items: [ { label: '插件统计', path: '/plugins' }, { label: '插件管理', path: '/plugins_manage' }, + { label: '命令索引', path: '/command_catalog' }, { label: '插件定时任务', path: '/plugin_schedules' }, { label: '群级插件配置', path: '/group_plugin_config' }, { label: '响应指令管理', path: '/fun_command_rules' }, @@ -1152,6 +1153,7 @@ '12': '/virtual_group', '13': '/api_docs', '14': '/system_status', + '18': '/command_catalog', '17': '/system_llm', '15': '/file_browser', '16': '/message_push' diff --git a/admin/dashboard/templates/command_catalog.html b/admin/dashboard/templates/command_catalog.html new file mode 100644 index 0000000..f00ee7c --- /dev/null +++ b/admin/dashboard/templates/command_catalog.html @@ -0,0 +1,478 @@ +{% extends "base.html" %} + +{% block title %}命令索引 - 机器人管理后台{% endblock %} + +{% block content %} +
+
+
+
Command Catalog
+

命令索引

+

集中查看当前插件命令、群可用状态、自动能力与管理员触发示例,减少靠记忆找功能的成本。

+
+
+ + + + + + 刷新索引 + +
+
+ + + + +
可用手动命令
+
{% raw %}{{ summary.available_manual_count || 0 }}{% endraw %}
+
当前群可以直接触发的消息命令
+
+
+ + +
自动能力
+
{% raw %}{{ summary.available_auto_count || 0 }}{% endraw %}
+
无需手动发送指令的自动/定时能力
+
+
+ + +
未启用命令
+
{% raw %}{{ summary.unavailable_manual_count || 0 }}{% endraw %}
+
管理员视角下可看到但当前群不可用的命令
+
+
+ + +
管理命令
+
{% raw %}{{ summary.admin_command_count || 0 }}{% endraw %}
+
群开关、管理员维护等后台辅助命令
+
+
+
+ + +
+
+

筛选条件

+

支持按命令、插件名、描述关键词快速定位。

+
+ + + +
+
+ + +
+
+

当前可用命令

+

这里展示的是当前群在管理员视角下“真实可触发”的命令入口。

+
+
+ {% raw %}{{ activeGroupLabel }}{% endraw %} +
+
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+

未启用命令

+

这部分只在后台管理员视角展示,便于你知道还有哪些能力没在当前群打开。

+
+
+ + + + + + + + + + + +
+
+ + +
+
+

自动/定时能力

+

用于提醒你哪些功能不是靠用户发命令触发,而是自动执行。

+
+
+
+
当前没有已启用的自动能力
+
+
+
{% raw %}{{ item.name }}{% endraw %}
+ {% raw %}{{ item.category_label }}{% endraw %} +
+
{% raw %}{{ item.description }}{% endraw %}
+
{% raw %}{{ item.availability_reason || '自动执行' }}{% endraw %}
+
+
+
+
+
+ + +
+
+

管理命令示例

+

给管理员的常用操作命令,适合快速开关功能和维护群管理员。

+
+
+
+
当前没有管理命令示例
+
+
+
{% raw %}{{ item.title }}{% endraw %}
+
+
{% raw %}{{ item.example }}{% endraw %}
+
{% raw %}{{ item.description }}{% endraw %}
+
+
+
+
+{% endblock %} + +{% block scripts %} + +{% endblock %} + +{% block styles %} + +{% endblock %} diff --git a/docs/工程优化与Feature清单.md b/docs/工程优化与Feature清单.md index eb10978..2b20d24 100644 --- a/docs/工程优化与Feature清单.md +++ b/docs/工程优化与Feature清单.md @@ -585,7 +585,8 @@ - 第一阶段已完成:`菜单 指令清单 / 功能清单 / 命令清单 / 帮助` 已改为基于运行中插件快照自动生成 - 第一阶段已完成:指令清单已按当前群真实可用状态过滤,管理员可额外看到未启用命令与管理命令 -- 后续可继续补充后台命令索引页、插件触发示例模板与更细粒度的分类标签 +- 第二阶段已完成:后台已新增“命令索引”页面,可按群查看真实可用命令、未启用命令、自动能力与管理员触发示例 +- 后续可继续补充插件触发示例模板、命令分类标签与更细粒度的使用说明 建议内容: diff --git a/plugins/robot_menu/menu_render_tool.py b/plugins/robot_menu/menu_render_tool.py index 60bb50e..b6286c6 100644 --- a/plugins/robot_menu/menu_render_tool.py +++ b/plugins/robot_menu/menu_render_tool.py @@ -297,7 +297,7 @@ class RobotMenuRenderTool: "status_label": str(normalized_snapshot.get("status_label") or "").strip(), } - def _collect_command_catalog(self, group_id: str, requester_id: str) -> dict: + def _collect_command_catalog(self, group_id: str, requester_id: str, force_admin: Optional[bool] = None) -> dict: """采集当前群和当前身份视角下的命令清单。 输出结构分三层: @@ -307,7 +307,10 @@ class RobotMenuRenderTool: """ plugin_manager = self._get_plugin_manager() snapshots = plugin_manager.get_plugin_snapshots() - is_admin = bool(GroupBotManager.is_admin_for_group(requester_id, group_id)) if group_id else bool(GroupBotManager.is_admin(requester_id)) + if force_admin is None: + is_admin = bool(GroupBotManager.is_admin_for_group(requester_id, group_id)) if group_id else bool(GroupBotManager.is_admin(requester_id)) + else: + is_admin = bool(force_admin) available_manual = [] available_auto = [] @@ -356,9 +359,13 @@ class RobotMenuRenderTool: "generated_at": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), } + def build_command_catalog_data(self, group_id: str, requester_id: str, force_admin: Optional[bool] = None) -> dict: + """对外暴露统一的命令目录结构,供机器人菜单和后台页面共同复用。""" + return self._collect_command_catalog(group_id, requester_id, force_admin=force_admin) + def build_command_catalog_text(self, group_id: str, requester_id: str) -> str: """构建适合直接发送给用户的文本版命令清单。""" - catalog = self._collect_command_catalog(group_id, requester_id) + catalog = self.build_command_catalog_data(group_id, requester_id) lines = [ "📚 当前群指令清单", f"群ID:{catalog['group_id'] or '私聊'}", @@ -411,7 +418,7 @@ class RobotMenuRenderTool: def build_command_catalog_markdown(self, group_id: str, requester_id: str) -> str: """构建适合图片渲染的 Markdown 版指令清单。""" - catalog = self._collect_command_catalog(group_id, requester_id) + catalog = self.build_command_catalog_data(group_id, requester_id) lines = [ "# 机器人指令清单", "",