From af487ff71e950f7fe6216cd6bcb260685be187df Mon Sep 17 00:00:00 2001
From: "feifei.xu" <307327147@qq.com>
Date: Sun, 15 Mar 2026 07:12:38 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E5=96=84=20Web=20UI=20?=
=?UTF-8?q?=E7=BB=86=E8=8A=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
新增页面:
- session_detail.html - 会话详情独立页面
- channel_edit.html - 频道配置编辑独立页面
- 错误页面 (401/403/404/500)
功能优化:
- 添加错误处理器支持 HTML 响应
- 更新编辑按钮跳转独立页面
- 完善暗黑主题支持
作者: 小黑 🐶
---
app/__init__.py | 12 +-
app/templates/config/channel_edit.html | 232 ++++++++++++++++++++++
app/templates/config/channels.html | 15 +-
app/templates/errors/401.html | 30 +++
app/templates/errors/403.html | 30 +++
app/templates/errors/404.html | 104 ++++++++++
app/templates/errors/500.html | 112 +++++++++++
app/templates/monitor/session_detail.html | 187 +++++++++++++++++
app/web/routes.py | 20 ++
9 files changed, 728 insertions(+), 14 deletions(-)
create mode 100644 app/templates/config/channel_edit.html
create mode 100644 app/templates/errors/401.html
create mode 100644 app/templates/errors/403.html
create mode 100644 app/templates/errors/404.html
create mode 100644 app/templates/errors/500.html
create mode 100644 app/templates/monitor/session_detail.html
diff --git a/app/__init__.py b/app/__init__.py
index e6f0c79..2d5d58d 100644
--- a/app/__init__.py
+++ b/app/__init__.py
@@ -123,24 +123,34 @@ def _configure_logging(app):
def _register_error_handlers(app):
"""注册错误处理器"""
- from flask import jsonify
+ from flask import jsonify, render_template, request, render_template
@app.errorhandler(400)
def bad_request(error):
+ if request.accepts('text/html'):
+ return render_template('errors/400.html', error=str(error)), 400
return jsonify({'error': 'Bad Request', 'message': str(error)}), 400
@app.errorhandler(401)
def unauthorized(error):
+ if request.accepts('text/html'):
+ return render_template('errors/401.html', error=str(error)), 401
return jsonify({'error': 'Unauthorized', 'message': str(error)}), 401
@app.errorhandler(403)
def forbidden(error):
+ if request.accepts('text/html'):
+ return render_template('errors/403.html', error=str(error)), 403
return jsonify({'error': 'Forbidden', 'message': str(error)}), 403
@app.errorhandler(404)
def not_found(error):
+ if request.accepts('text/html'):
+ return render_template('errors/404.html', error=str(error)), 404
return jsonify({'error': 'Not Found', 'message': str(error)}), 404
@app.errorhandler(500)
def internal_error(error):
+ if request.accepts('text/html'):
+ return render_template('errors/500.html', error=str(error)), 500
return jsonify({'error': 'Internal Server Error', 'message': str(error)}), 500
diff --git a/app/templates/config/channel_edit.html b/app/templates/config/channel_edit.html
new file mode 100644
index 0000000..d183150
--- /dev/null
+++ b/app/templates/config/channel_edit.html
@@ -0,0 +1,232 @@
+{% extends "base.html" %}
+
+{% block title %}编辑频道 - 智队中枢{% endblock %}
+
+{% block content %}
+
+ {# 页面头部 #}
+
+
+
+
+
+
+
编辑频道配置
+
{{ config.name }}
+
+
+
+
+ {# 表单 #}
+
+
+
+
+{% endblock %}
diff --git a/app/templates/config/channels.html b/app/templates/config/channels.html
index 403de45..9c252ae 100644
--- a/app/templates/config/channels.html
+++ b/app/templates/config/channels.html
@@ -148,20 +148,9 @@
});
}
- // 编辑频道
+ // 编辑频道 - 跳转到独立编辑页面
function editChannel(id) {
- fetch(`/api/web/channels/${id}`)
- .then(res => res.json())
- .then(data => {
- document.getElementById('modal-title').textContent = '编辑配置';
- document.getElementById('channel-id').value = data.id;
- document.getElementById('channel-name').value = data.name;
- document.getElementById('channel-url').value = data.gateway_url;
- document.getElementById('channel-reconnect').value = data.reconnect_interval;
- document.getElementById('channel-heartbeat').value = data.heartbeat_interval;
- document.getElementById('channel-enabled').checked = data.enabled;
- showModal('channel-modal');
- });
+ window.location.href = `/web/config/channels/${id}/edit`;
}
// 删除频道
diff --git a/app/templates/errors/401.html b/app/templates/errors/401.html
new file mode 100644
index 0000000..2c7222f
--- /dev/null
+++ b/app/templates/errors/401.html
@@ -0,0 +1,30 @@
+
+
+
+
+
+ 401 - 未授权 | 智队中枢
+
+
+
+
+
+
+
401
+
+
+
智队中枢 v0.7.0
+
+
+
+
diff --git a/app/templates/errors/403.html b/app/templates/errors/403.html
new file mode 100644
index 0000000..b1dc297
--- /dev/null
+++ b/app/templates/errors/403.html
@@ -0,0 +1,30 @@
+
+
+
+
+
+ 403 - 禁止访问 | 智队中枢
+
+
+
+
+
+
+
403
+
+
+
智队中枢 v0.7.0
+
+
+
+
diff --git a/app/templates/errors/404.html b/app/templates/errors/404.html
new file mode 100644
index 0000000..310b795
--- /dev/null
+++ b/app/templates/errors/404.html
@@ -0,0 +1,104 @@
+
+
+
+
+
+ 404 - 页面未找到 | 智队中枢
+
+ {# Tailwind CSS #}
+
+
+
+
+
+
+
+ {# 404 数字 #}
+
+ 404
+
+
+ {# 错误信息 #}
+
+
页面未找到
+
抱歉,您访问的页面不存在或已被移除
+
+
+ {# 操作按钮 #}
+
+
+ {# 建议 #}
+
+
您可以尝试
+
+ -
+
+ 检查 URL 是否正确
+
+ -
+
+ 刷新页面
+
+ -
+
+ 联系管理员
+
+
+
+
+ {# 页脚 #}
+
+
+
+
+
+
diff --git a/app/templates/errors/500.html b/app/templates/errors/500.html
new file mode 100644
index 0000000..e74e1c3
--- /dev/null
+++ b/app/templates/errors/500.html
@@ -0,0 +1,112 @@
+
+
+
+
+
+ 500 - 服务器错误 | 智队中枢
+
+ {# Tailwind CSS #}
+
+
+
+
+
+
+
+ {# 500 数字 #}
+
+ 500
+
+
+ {# 错误信息 #}
+
+
服务器错误
+
抱歉,服务器遇到了一个意外情况
+
+
+ {# 操作按钮 #}
+
+
+ {# 错误详情 #}
+ {% if error %}
+
+ {% endif %}
+
+ {# 建议 #}
+
+
如果问题持续存在
+
+ -
+
+ 稍后再试
+
+ -
+
+ 清除浏览器缓存
+
+ -
+
+ 联系管理员报告问题
+
+
+
+
+ {# 页脚 #}
+
+
+
+
+
+
diff --git a/app/templates/monitor/session_detail.html b/app/templates/monitor/session_detail.html
new file mode 100644
index 0000000..c1e6c19
--- /dev/null
+++ b/app/templates/monitor/session_detail.html
@@ -0,0 +1,187 @@
+{% extends "base.html" %}
+
+{% block title %}会话详情 - 智队中枢{% endblock %}
+
+{% block content %}
+
+ {# 页面头部 #}
+
+
+
+
+
+
+
会话详情
+
ID: {{ session.id }}
+
+
+
+ {% if session.status == 'active' %}
+
+ {% endif %}
+
+
+
+
+ {# 会话信息卡片 #}
+
+
+
用户
+
+
+
+ {{ session.user.username[0] if session.user else '?' }}
+
+
+ {{ session.user.username if session.user else '匿名用户' }}
+
+
+
+
主 Agent
+
+ {{ session.primary_agent.name if session.primary_agent else '未分配' }}
+
+
+
+
状态
+
+ {% if session.status == 'active' %}
+
+
+ 活跃
+
+ {% elif session.status == 'paused' %}
+ 暂停
+ {% else %}
+ 已关闭
+ {% endif %}
+
+
+
+
消息数
+
{{ session.message_count }}
+
+
+
+ {# 时间线 #}
+
+
+
+
+
+
创建时间
+
{{ session.created_at.strftime('%Y-%m-%d %H:%M:%S') if session.created_at else '-' }}
+
+
+
+
最后活跃
+
{{ session.last_active_at.strftime('%Y-%m-%d %H:%M:%S') if session.last_active_at else '-' }}
+
+
+
+
更新时间
+
{{ session.updated_at.strftime('%Y-%m-%d %H:%M:%S') if session.updated_at else '-' }}
+
+
+
+
+
+ {# 消息记录 #}
+
+
+
+ {% if messages %}
+
+ {% for msg in messages %}
+
+
+
+
+ {{ 'Agent' if msg.sender_type == 'agent' else ('用户' if msg.sender_type == 'user' else '系统') }}
+
+
{{ msg.created_at.strftime('%H:%M:%S') if msg.created_at else '' }}
+ {% if msg.status == 'sent' %}
+
+ {% elif msg.status == 'delivered' %}
+
+ {% endif %}
+
+
{{ msg.content }}
+ {% if msg.message_type == 'media' %}
+
+ {% endif %}
+
+
+ {% endfor %}
+
+ {% else %}
+
+ {% endif %}
+
+
+
+
+
+{% endblock %}
diff --git a/app/web/routes.py b/app/web/routes.py
index 0f38a11..0ea9777 100644
--- a/app/web/routes.py
+++ b/app/web/routes.py
@@ -57,3 +57,23 @@ def sessions():
agents = Agent.query.all()
sessions = Session.query.order_by(Session.last_active_at.desc()).limit(50).all()
return render_template('monitor/sessions.html', sessions=sessions, agents=agents)
+
+
+@web_bp.route('/monitor/sessions/')
+@jwt_required()
+def session_detail(session_id):
+ """会话详情页面"""
+ session = Session.query.get_or_404(session_id)
+ messages = Message.query.filter_by(session_id=session_id).order_by(
+ Message.created_at.asc()
+ ).limit(200).all()
+ return render_template('monitor/session_detail.html', session=session, messages=messages)
+
+
+@web_bp.route('/config/channels//edit')
+@jwt_required()
+def channel_edit(channel_id):
+ """编辑频道配置页面"""
+ from app.models.channel_config import ChannelConfig
+ config = ChannelConfig.query.get_or_404(channel_id)
+ return render_template('config/channel_edit.html', config=config)