功能设计:
1. 智队频道插件配置管理
2. 一键测试频道插件连接
3. 会话监控与消息查看
技术栈:
- Jinja2 + HTMX + Tailwind CSS
- Chart.js 图表
- WebSocket 实时推送
预计开发时间: 6 天
作者: 小白 🐶
31 KiB
31 KiB
智队中枢 - Web 管理界面技术方案
智队中枢 Web UI 设计文档
📋 概述
为智队中枢添加 Web 管理界面,提供:
- 智队频道插件配置管理
- 一键测试频道插件连接
- 会话监控与消息查看
🏗️ 技术架构
整体架构
┌─────────────────────────────────────────────────────────────────────────────┐
│ 智队中枢 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. 频道配置数据模型
# 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. 连接测试服务
# 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
# 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/<id>/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/<id>')
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 | 作者: 小白 🐶