docs: 新增 Web 管理界面技术方案
功能设计:
1. 智队频道插件配置管理
2. 一键测试频道插件连接
3. 会话监控与消息查看
技术栈:
- Jinja2 + HTMX + Tailwind CSS
- Chart.js 图表
- WebSocket 实时推送
预计开发时间: 6 天
作者: 小白 🐶
This commit is contained in:
570
docs/WEB_UI_SPEC.md
Normal file
570
docs/WEB_UI_SPEC.md
Normal file
@@ -0,0 +1,570 @@
|
|||||||
|
# 智队中枢 - 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/<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 | 作者: 小白 🐶*
|
||||||
Reference in New Issue
Block a user