# 智队中枢 - Web 管理界面技术方案 > 智队中枢 Web UI 设计文档 ## 📋 概述 为智队中枢添加 Web 管理界面,提供: 1. 智队频道插件配置管理 2. 一键测试频道插件连接 3. 会话监控与消息查看 --- ## 🏗️ 技术架构 ### 整体架构 ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ 智队中枢 Web UI │ │ ┌───────────────────────────────────────────────────────────────────────┐ │ │ │ 前端 (Jinja2 + HTMX + Tailwind) │ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ │ │ 配置管理 │ │ 连接测试 │ │ 会话监控 │ │ │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ └───────────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ┌───────────────────────────────────────────────────────────────────────┐ │ │ │ 后端 API (Flask Blueprint) │ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ │ │ /web/* │ │ /api/web/* │ │ /ws/* │ │ │ │ │ │ 页面路由 │ │ 数据接口 │ │ 实时推送 │ │ │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ └───────────────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────────┘ ``` ### 技术选型 | 层级 | 技术 | 说明 | |------|------|------| | 模板引擎 | Jinja2 | Flask 原生支持 | | 交互增强 | HTMX | 无需写 JS,HTML 属性驱动 | | 样式框架 | Tailwind CSS | 快速构建 UI | | 图表 | Chart.js | 会话统计图表 | | 实时更新 | WebSocket | 会话状态实时推送 | --- ## 📁 项目结构 ``` pit-router/ ├── app/ │ ├── web/ # Web UI 模块 (新增) │ │ ├── __init__.py # Blueprint 注册 │ │ ├── routes.py # 页面路由 │ │ ├── api.py # 数据 API │ │ └── utils.py # 工具函数 │ ├── templates/ # 模板文件 (新增) │ │ ├── base.html # 基础模板 │ │ ├── index.html # 首页/仪表盘 │ │ ├── config/ # 配置管理 │ │ │ ├── channels.html # 频道配置列表 │ │ │ └── channel_edit.html # 频道配置编辑 │ │ ├── monitor/ # 会话监控 │ │ │ ├── sessions.html # 会话列表 │ │ │ ├── session_detail.html # 会话详情 │ │ │ └── messages.html # 消息查看 │ │ └── components/ # 组件模板 │ │ ├── navbar.html # 导航栏 │ │ ├── sidebar.html # 侧边栏 │ │ └── toast.html # 提示消息 │ └── static/ # 静态资源 (新增) │ ├── css/ │ │ └── style.css # 自定义样式 │ └── js/ │ └── app.js # 自定义脚本 └── ... ``` --- ## 🎨 页面设计 ### 1. 首页/仪表盘 ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ 智队中枢 [用户] [设置] [登出] │ ├──────────────┬──────────────────────────────────────────────────────────────┤ │ │ │ │ 📊 仪表盘 │ 系统状态 │ │ ──────── │ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ │ │ │ 在线 Agent │ │ 活跃会话 │ │ 今日消息 │ │ │ ⚙️ 配置管理 │ │ 5 │ │ 12 │ │ 1,234 │ │ │ └ 频道配置 │ └────────────┘ └────────────┘ └────────────┘ │ │ │ │ │ 📡 连接测试 │ 会话趋势 (最近 24 小时) │ │ └ 测试面板 │ ┌────────────────────────────────────────────────────┐ │ │ │ │ 📈 │ │ │ 👁️ 会话监控 │ │ ████ │ │ │ └ 会话列表 │ │ ████████ ████████ │ │ │ └ 消息记录 │ │ ████████████████████████████████ │ │ │ │ └────────────────────────────────────────────────────┘ │ │ │ │ │ │ 最近会话 │ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ │ 用户 Agent 消息数 状态 时间 │ │ │ │ │ yunxiafei 小白 15 活跃 2分钟前 │ │ │ │ │ xiaobai 小黑 8 活跃 5分钟前 │ │ │ │ │ test_user 小花 23 已关闭 1小时前 │ │ │ │ └────────────────────────────────────────────────────┘ │ └──────────────┴──────────────────────────────────────────────────────────────┘ ``` ### 2. 频道配置页面 ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ 智队中枢 > 配置管理 > 频道配置 │ ├──────────────┬──────────────────────────────────────────────────────────────┤ │ │ │ │ 📊 仪表盘 │ 智队频道插件配置 [+ 新增配置] │ │ ──────── │ ┌────────────────────────────────────────────────────┐ │ │ │ │ 名称 Gateway URL 状态 操作 │ │ │ ⚙️ 配置管理 │ ├────────────────────────────────────────────────────┤ │ │ └ 频道配置 │ │ 默认频道 ws://localhost:18888 ✅ 在线 [编辑][测试] │ │ │ │ 工作频道 ws://work:18888 ⚠️ 离线 [编辑][测试] │ │ 📡 连接测试 │ │ 测试频道 ws://test:18888 ✅ 在线 [编辑][测试] │ │ └ 测试面板 │ └────────────────────────────────────────────────────┘ │ │ │ │ │ 👁️ 会话监控 │ 配置详情 (点击编辑后显示) │ │ └ 会话列表 │ ┌────────────────────────────────────────────────────┐ │ │ └ 消息记录 │ │ Gateway URL: [ws://localhost:18888 ] │ │ │ │ │ Auth Token: [•••••••••••••••• ] │ │ │ │ │ 重连间隔: [5000] 毫秒 │ │ │ │ │ 心跳间隔: [30000] 毫秒 │ │ │ │ │ 启用状态: [✓] 启用 │ │ │ │ │ │ │ │ │ │ [取消] [保存] │ │ │ │ └────────────────────────────────────────────────────┘ │ └──────────────┴──────────────────────────────────────────────────────────────┘ ``` ### 3. 连接测试页面 ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ 智队中枢 > 连接测试 │ ├──────────────┬──────────────────────────────────────────────────────────────┤ │ │ │ │ 📊 仪表盘 │ 连接测试 │ │ ──────── │ ┌────────────────────────────────────────────────────┐ │ │ │ │ 选择频道: [默认频道 ▼] │ │ │ ⚙️ 配置管理 │ │ │ │ │ └ 频道配置 │ │ [🚀 开始测试] │ │ │ │ └────────────────────────────────────────────────────┘ │ │ 📡 连接测试 │ │ │ └ 测试面板 │ 测试结果 │ │ │ ┌────────────────────────────────────────────────────┐ │ │ 👁️ 会话监控 │ │ ✅ WebSocket 连接成功 │ │ │ └ 会话列表 │ │ ✅ 认证通过 │ │ │ └ 消息记录 │ │ ✅ 心跳响应正常 │ │ │ │ │ ✅ 消息收发测试通过 │ │ │ │ │ │ │ │ │ │ 响应时间: 45ms │ │ │ │ │ 测试时间: 2026-03-14 22:10:00 │ │ │ │ └────────────────────────────────────────────────────┘ │ │ │ │ │ │ 测试日志 │ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ │ [INFO] 正在连接 ws://localhost:18888... │ │ │ │ │ [INFO] WebSocket 连接已建立 │ │ │ │ │ [INFO] 发送认证请求... │ │ │ │ │ [INFO] 认证成功: agent_id=xiaobai │ │ │ │ │ [INFO] 发送心跳... │ │ │ │ │ [INFO] 心跳响应: pong │ │ │ │ │ [INFO] 发送测试消息... │ │ │ │ │ [INFO] 收到响应: Hello from Agent │ │ │ │ │ [INFO] 测试完成 │ │ │ │ └────────────────────────────────────────────────────┘ │ └──────────────┴──────────────────────────────────────────────────────────────┘ ``` ### 4. 会话监控页面 ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ 智队中枢 > 会话监控 │ ├──────────────┬──────────────────────────────────────────────────────────────┤ │ │ │ │ 📊 仪表盘 │ 会话列表 [🔄 刷新] │ │ ──────── │ ┌────────────────────────────────────────────────────┐ │ │ │ │ 筛选: Agent [全部▼] 状态 [全部▼] 时间 [今天▼] │ │ │ ⚙️ 配置管理 │ ├────────────────────────────────────────────────────┤ │ │ └ 频道配置 │ │ ID 用户 Agent 消息 状态 时间 │ │ │ │ ├────────────────────────────────────────────────────┤ │ │ 📡 连接测试 │ │ sess_001 yunxiafei 小白 15 🟢活跃 2分前│ │ │ └ 测试面板 │ │ sess_002 xiaobai 小黑 8 🟢活跃 5分前│ │ │ │ │ sess_003 test_user 小花 23 ⚪关闭 1时前│ │ │ 👁️ 会话监控 │ │ sess_004 admin 小白 42 🟡暂停 2时前│ │ │ └ 会话列表 │ │ sess_005 guest 小花 3 🟢活跃 10分前│ │ │ └ 消息记录 │ └────────────────────────────────────────────────────┘ │ │ │ │ │ │ 会话详情: sess_001 │ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ │ 用户: yunxiafei Agent: 小白 状态: 🟢 活跃 │ │ │ │ │ 创建: 2026-03-14 20:00:00 │ │ │ │ │ 最后活跃: 2026-03-14 22:08:00 │ │ │ │ ├────────────────────────────────────────────────────┤ │ │ │ │ 消息记录: │ │ │ │ │ ┌──────────────────────────────────────────────┐ │ │ │ │ │ │ [用户] 你好小白 │ │ │ │ │ │ │ [小白] 你好!有什么可以帮你的? │ │ │ │ │ │ │ [用户] 帮我写一个 Flask 应用 │ │ │ │ │ │ │ [小白] 好的,我来帮你创建一个 Flask 应用... │ │ │ │ │ │ │ ... │ │ │ │ │ │ └──────────────────────────────────────────────┘ │ │ │ │ │ [关闭会话] [导出记录] │ │ │ │ └────────────────────────────────────────────────────┘ │ └──────────────┴──────────────────────────────────────────────────────────────┘ ``` --- ## 🔌 API 设计 ### Web UI 路由 | 方法 | 路径 | 说明 | |------|------|------| | GET | /web/ | 首页/仪表盘 | | GET | /web/config/channels | 频道配置列表 | | GET | /web/config/channels/new | 新增频道配置 | | GET | /web/config/channels/:id/edit | 编辑频道配置 | | GET | /web/test | 连接测试页面 | | GET | /web/monitor/sessions | 会话监控列表 | | GET | /web/monitor/sessions/:id | 会话详情 | ### Web UI 数据 API | 方法 | 路径 | 说明 | |------|------|------| | GET | /api/web/stats | 系统统计数据 | | GET | /api/web/channels | 频道配置列表 | | POST | /api/web/channels | 创建频道配置 | | PUT | /api/web/channels/:id | 更新频道配置 | | DELETE | /api/web/channels/:id | 删除频道配置 | | POST | /api/web/channels/:id/test | 测试频道连接 | | GET | /api/web/sessions | 会话列表 (带筛选) | | GET | /api/web/sessions/:id | 会话详情 | | GET | /api/web/sessions/:id/messages | 会话消息 | | PUT | /api/web/sessions/:id/close | 关闭会话 | --- ## 🔧 核心实现 ### 1. 频道配置数据模型 ```python # app/models/channel_config.py from app import db from datetime import datetime import uuid class ChannelConfig(db.Model): """智队频道插件配置""" __tablename__ = 'channel_configs' id = db.Column(db.String(36), primary_key=True, default=lambda: str(uuid.uuid4())) name = db.Column(db.String(80), nullable=False, unique=True) gateway_url = db.Column(db.String(256), nullable=False) auth_token = db.Column(db.String(256), nullable=True) reconnect_interval = db.Column(db.Integer, default=5000) heartbeat_interval = db.Column(db.Integer, default=30000) enabled = db.Column(db.Boolean, default=True) # 状态 status = db.Column(db.String(20), default='offline') last_connected = db.Column(db.DateTime, nullable=True) last_error = db.Column(db.Text, nullable=True) # 时间戳 created_at = db.Column(db.DateTime, default=datetime.utcnow) updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) def to_dict(self): return { 'id': self.id, 'name': self.name, 'gateway_url': self.gateway_url, 'auth_token': '••••••••' if self.auth_token else None, 'reconnect_interval': self.reconnect_interval, 'heartbeat_interval': self.heartbeat_interval, 'enabled': self.enabled, 'status': self.status, 'last_connected': self.last_connected.isoformat() if self.last_connected else None, 'created_at': self.created_at.isoformat() } ``` ### 2. 连接测试服务 ```python # app/services/channel_tester.py import asyncio import websockets import json import time from datetime import datetime class ChannelTester: """频道连接测试器""" def __init__(self, config): self.config = config self.results = [] self.start_time = None async def test_connection(self): """执行连接测试""" self.start_time = time.time() self.results = [] try: # 1. WebSocket 连接测试 await self._test_websocket() # 2. 认证测试 await self._test_auth() # 3. 心跳测试 await self._test_heartbeat() # 4. 消息收发测试 await self._test_message() except Exception as e: self._log('ERROR', str(e)) return { 'success': all(r['success'] for r in self.results), 'results': self.results, 'response_time': int((time.time() - self.start_time) * 1000), 'tested_at': datetime.utcnow().isoformat() } async def _test_websocket(self): """测试 WebSocket 连接""" self._log('INFO', f'正在连接 {self.config.gateway_url}...') try: self.ws = await websockets.connect( self.config.gateway_url, extra_headers={'Authorization': f'Bearer {self.config.auth_token}'} ) self._log('INFO', 'WebSocket 连接已建立', success=True) except Exception as e: self._log('ERROR', f'连接失败: {e}', success=False) raise async def _test_auth(self): """测试认证""" self._log('INFO', '发送认证请求...') try: # 发送认证消息 await self.ws.send(json.dumps({ 'type': 'auth', 'token': self.config.auth_token })) # 等待响应 response = await asyncio.wait_for(self.ws.recv(), timeout=10) data = json.loads(response) if data.get('type') == 'auth_success': self._log('INFO', f"认证成功: agent_id={data.get('agent_id')}", success=True) else: self._log('ERROR', f"认证失败: {data}", success=False) raise Exception('认证失败') except Exception as e: self._log('ERROR', f'认证错误: {e}', success=False) raise async def _test_heartbeat(self): """测试心跳""" self._log('INFO', '发送心跳...') try: await self.ws.send(json.dumps({'type': 'ping'})) response = await asyncio.wait_for(self.ws.recv(), timeout=10) data = json.loads(response) if data.get('type') == 'pong': self._log('INFO', '心跳响应: pong', success=True) else: self._log('WARNING', f'心跳响应异常: {data}', success=True) except Exception as e: self._log('ERROR', f'心跳错误: {e}', success=False) async def _test_message(self): """测试消息收发""" self._log('INFO', '发送测试消息...') try: test_msg = { 'type': 'message', 'content': '__TEST__' } await self.ws.send(json.dumps(test_msg)) response = await asyncio.wait_for(self.ws.recv(), timeout=30) data = json.loads(response) self._log('INFO', f"收到响应: {data.get('content', data)[:50]}", success=True) except Exception as e: self._log('WARNING', f'消息测试跳过: {e}', success=True) await self.ws.close() self._log('INFO', '测试完成') def _log(self, level, message, success=None): """记录日志""" entry = { 'level': level, 'message': message, 'timestamp': datetime.utcnow().isoformat(), 'success': success if success is not None else level == 'INFO' } self.results.append(entry) ``` ### 3. Web UI Blueprint ```python # app/web/routes.py from flask import Blueprint, render_template, request, redirect, url_for from app.models import Session, Agent, Gateway, Message from app.models.channel_config import ChannelConfig from app import db from datetime import datetime, timedelta web_bp = Blueprint('web', __name__, url_prefix='/web') @web_bp.route('/') def index(): """首页/仪表盘""" # 统计数据 stats = { 'online_agents': Agent.query.filter_by(status='online').count(), 'active_sessions': Session.query.filter_by(status='active').count(), 'today_messages': Message.query.filter( Message.created_at >= datetime.utcnow() - timedelta(days=1) ).count() } # 最近会话 recent_sessions = Session.query.order_by( Session.last_active_at.desc() ).limit(5).all() return render_template('index.html', stats=stats, recent_sessions=recent_sessions) @web_bp.route('/config/channels') def channels(): """频道配置列表""" configs = ChannelConfig.query.all() return render_template('config/channels.html', configs=configs) @web_bp.route('/config/channels//edit') def channel_edit(id): """编辑频道配置""" config = ChannelConfig.query.get_or_404(id) return render_template('config/channel_edit.html', config=config) @web_bp.route('/test') def test(): """连接测试页面""" configs = ChannelConfig.query.filter_by(enabled=True).all() return render_template('test/index.html', configs=configs) @web_bp.route('/monitor/sessions') def sessions(): """会话监控""" status = request.args.get('status') agent_id = request.args.get('agent_id') query = Session.query if status: query = query.filter_by(status=status) if agent_id: query = query.filter_by(agent_id=agent_id) sessions = query.order_by(Session.last_active_at.desc()).all() agents = Agent.query.all() return render_template('monitor/sessions.html', sessions=sessions, agents=agents) @web_bp.route('/monitor/sessions/') def session_detail(id): """会话详情""" session = Session.query.get_or_404(id) messages = Message.query.filter_by(session_id=id).order_by( Message.created_at.asc() ).limit(100).all() return render_template('monitor/session_detail.html', session=session, messages=messages) ``` --- ## 📦 依赖更新 ### requirements.txt 新增 ``` # Web UI flask-htmx==0.3.0 ``` --- ## 📈 开发计划 ### Phase 5: Web UI 开发 | 任务 | 预计时间 | 说明 | |------|----------|------| | 项目结构调整 | 0.5 天 | 创建 templates、static 目录 | | 基础模板 | 0.5 天 | base.html、导航、侧边栏 | | 首页仪表盘 | 1 天 | 统计数据、图表 | | 频道配置 | 1 天 | CRUD、表单验证 | | 连接测试 | 1 天 | WebSocket 测试、日志显示 | | 会话监控 | 1 天 | 列表、详情、实时更新 | | 样式美化 | 0.5 天 | Tailwind 样式优化 | | 测试 | 0.5 天 | 功能测试 | **总计:6 天** --- ## 🎯 里程碑 | 阶段 | 功能 | 预计完成 | |------|------|----------| | M1 | 基础框架 + 首页 | Day 2 | | M2 | 频道配置管理 | Day 3 | | M3 | 连接测试 | Day 4 | | M4 | 会话监控 | Day 5 | | M5 | 样式优化 + 测试 | Day 6 | --- *文档版本: v1.0 | 创建时间: 2026-03-14 | 作者: 小白 🐶*