From e24c26f1fb11ef8854ab80428a01af5c17ee93be Mon Sep 17 00:00:00 2001 From: yunxiafei <307327147@qq.com> Date: Sun, 15 Mar 2026 07:32:50 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=EF=BC=8C=E6=94=AF=E6=8C=81=E5=A4=96=E7=BD=91?= =?UTF-8?q?=E8=AE=BF=E9=97=AE=20Web=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 /web/login 登录页面 - 修改路由支持可选认证 - 前端自动检测 token 并跳转登录 - 更新 .gitignore 排除 venv --- app/web/routes.py | 101 +++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 59 deletions(-) diff --git a/app/web/routes.py b/app/web/routes.py index cf19fb5..00d0802 100644 --- a/app/web/routes.py +++ b/app/web/routes.py @@ -3,7 +3,7 @@ Web UI Blueprint 智队中枢 Web 管理界面 """ from flask import Blueprint, render_template, request, jsonify, redirect, url_for -from flask_jwt_extended import jwt_required, get_jwt_identity, verify_jwt_in_request, optional +from flask_jwt_extended import jwt_required, get_jwt_identity from datetime import datetime, timedelta from app.models import db, User, Session, Agent, Gateway, Message @@ -17,24 +17,14 @@ def login(): @web_bp.route('/') -@jwt_required(optional=True) def index(): """首页/仪表盘""" try: - verify_jwt_in_request(optional=True) - user_id = get_jwt_identity() - - if not user_id: - # 未登录,返回空数据页面,前端会跳转到登录 - stats = { - 'online_agents': 0, - 'active_sessions': 0, - 'today_messages': 0, - 'online_gateways': 0, - } - recent_sessions = [] - else: - # 已登录,获取真实数据 + from flask_jwt_extended import decode_token + from flask import request + token = request.cookies.get('access_token') or request.headers.get('Authorization', '').replace('Bearer ', '') + if token: + user_id = decode_token(token).get('sub') stats = { 'online_agents': Agent.query.filter_by(status='online').count(), 'active_sessions': Session.query.filter_by(status='active').count(), @@ -46,65 +36,63 @@ def index(): recent_sessions = Session.query.order_by( Session.last_active_at.desc() ).limit(5).all() + else: + stats = {'online_agents': 0, 'active_sessions': 0, 'today_messages': 0, 'online_gateways': 0} + recent_sessions = [] except: - stats = { - 'online_agents': 0, - 'active_sessions': 0, - 'today_messages': 0, - 'online_gateways': 0, - } + stats = {'online_agents': 0, 'active_sessions': 0, 'today_messages': 0, 'online_gateways': 0} recent_sessions = [] return render_template('index.html', stats=stats, recent_sessions=recent_sessions) @web_bp.route('/config/channels') -@jwt_required(optional=True) def channels(): """频道配置列表""" try: - verify_jwt_in_request(optional=True) - user_id = get_jwt_identity() - if not user_id: - configs = [] - else: + from flask_jwt_extended import decode_token + from flask import request + token = request.cookies.get('access_token') or request.headers.get('Authorization', '').replace('Bearer ', '') + if token: from app.models.channel_config import ChannelConfig configs = ChannelConfig.query.all() + else: + configs = [] except: configs = [] return render_template('config/channels.html', configs=configs) @web_bp.route('/test') -@jwt_required(optional=True) def test(): """连接测试页面""" try: - verify_jwt_in_request(optional=True) - user_id = get_jwt_identity() - if not user_id: - configs = [] - else: + from flask_jwt_extended import decode_token + from flask import request + token = request.cookies.get('access_token') or request.headers.get('Authorization', '').replace('Bearer ', '') + if token: from app.models.channel_config import ChannelConfig configs = ChannelConfig.query.filter_by(enabled=True).all() + else: + configs = [] except: configs = [] return render_template('test/index.html', configs=configs) @web_bp.route('/monitor/sessions') -@jwt_required(optional=True) def sessions(): """会话监控""" try: - verify_jwt_in_request(optional=True) - user_id = get_jwt_identity() - if not user_id: - agents = [] - sessions = [] - else: + from flask_jwt_extended import decode_token + from flask import request + token = request.cookies.get('access_token') or request.headers.get('Authorization', '').replace('Bearer ', '') + if token: agents = Agent.query.all() sessions = Session.query.order_by(Session.last_active_at.desc()).limit(50).all() + else: + agents = [] + sessions = [] except: agents = [] sessions = [] @@ -112,36 +100,31 @@ def sessions(): @web_bp.route('/monitor/sessions/') -@jwt_required(optional=True) def session_detail(session_id): """会话详情页面""" try: - verify_jwt_in_request(optional=True) - user_id = get_jwt_identity() - if not user_id: - session = None - messages = [] - else: - 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() + from flask_jwt_extended import decode_token + from flask import request + token = request.cookies.get('access_token') or request.headers.get('Authorization', '').replace('Bearer ', '') + if not token: + return render_template('errors/401.html'), 401 + 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() except: - session = None - messages = [] - if session is None: return render_template('errors/401.html'), 401 return render_template('monitor/session_detail.html', session=session, messages=messages) @web_bp.route('/config/channels//edit') -@jwt_required(optional=True) def channel_edit(channel_id): """编辑频道配置页面""" try: - verify_jwt_in_request(optional=True) - user_id = get_jwt_identity() - if not user_id: + from flask_jwt_extended import decode_token + from flask import request + token = request.cookies.get('access_token') or request.headers.get('Authorization', '').replace('Bearer ', '') + if not token: return render_template('errors/401.html'), 401 from app.models.channel_config import ChannelConfig config = ChannelConfig.query.get_or_404(channel_id)