203 lines
6.0 KiB
Python
203 lines
6.0 KiB
Python
# 文件位置: app/__init__.py
|
||
# 文件名: __init__.py
|
||
|
||
"""
|
||
Flask应用工厂
|
||
"""
|
||
import os
|
||
import logging
|
||
from flask import Flask, render_template, jsonify
|
||
from flask_cors import CORS
|
||
from flask_socketio import SocketIO
|
||
from config import config
|
||
|
||
# 创建SocketIO实例
|
||
socketio = SocketIO()
|
||
|
||
def create_app(config_name=None):
|
||
"""创建Flask应用"""
|
||
if config_name is None:
|
||
config_name = os.environ.get('FLASK_CONFIG', 'development')
|
||
|
||
# 创建Flask应用
|
||
app = Flask(__name__)
|
||
|
||
# 加载配置
|
||
app.config.from_object(config[config_name])
|
||
config[config_name].init_app(app)
|
||
|
||
# 初始化扩展
|
||
CORS(app, resources={r"/api/*": {"origins": "*"}})
|
||
socketio.init_app(app,
|
||
cors_allowed_origins="*",
|
||
async_mode='eventlet',
|
||
logger=True,
|
||
engineio_logger=True if app.debug else False)
|
||
|
||
# 配置日志
|
||
setup_logging(app)
|
||
|
||
# 注册蓝图
|
||
register_blueprints(app)
|
||
|
||
# 注册WebSocket事件处理器
|
||
with app.app_context():
|
||
from app.routes.websocket import register_handlers
|
||
register_handlers(socketio)
|
||
|
||
# 注册错误处理器
|
||
register_error_handlers(app)
|
||
|
||
# 创建必要的目录
|
||
create_directories(app)
|
||
|
||
# 初始化任务管理器
|
||
init_task_manager(app)
|
||
|
||
app.logger.info(f'DeepResearch应用已创建,配置: {config_name}')
|
||
|
||
return app
|
||
|
||
def register_blueprints(app):
|
||
"""注册所有蓝图"""
|
||
from app.routes.main import main_bp
|
||
from app.routes.api import api_bp
|
||
from app.routes.frontend import frontend_bp
|
||
|
||
# 先注册前端路由,确保 '/' 路由正确
|
||
app.register_blueprint(frontend_bp)
|
||
app.register_blueprint(api_bp, url_prefix='/api')
|
||
app.register_blueprint(main_bp)
|
||
|
||
app.logger.info('蓝图注册完成')
|
||
|
||
def register_error_handlers(app):
|
||
"""注册错误处理器"""
|
||
|
||
@app.errorhandler(404)
|
||
def not_found_error(error):
|
||
if request.path.startswith('/api/'):
|
||
return jsonify({'error': 'Not found'}), 404
|
||
return render_template('404.html'), 404
|
||
|
||
@app.errorhandler(500)
|
||
def internal_error(error):
|
||
app.logger.error(f'服务器错误: {error}')
|
||
if request.path.startswith('/api/'):
|
||
return jsonify({'error': 'Internal server error'}), 500
|
||
return render_template('500.html'), 500
|
||
|
||
@app.errorhandler(Exception)
|
||
def unhandled_exception(error):
|
||
app.logger.error(f'未处理的异常: {error}', exc_info=True)
|
||
if request.path.startswith('/api/'):
|
||
return jsonify({'error': str(error)}), 500
|
||
return render_template('500.html'), 500
|
||
|
||
def setup_logging(app):
|
||
"""设置日志系统"""
|
||
from app.utils.logger import setup_logging as logger_setup
|
||
logger_setup(app)
|
||
|
||
# 设置依赖库的日志级别
|
||
logging.getLogger('werkzeug').setLevel(logging.WARNING)
|
||
logging.getLogger('socketio').setLevel(logging.INFO if app.debug else logging.WARNING)
|
||
logging.getLogger('engineio').setLevel(logging.INFO if app.debug else logging.WARNING)
|
||
|
||
def create_directories(app):
|
||
"""创建必要的目录"""
|
||
directories = [
|
||
app.config.get('DATA_DIR'),
|
||
app.config.get('SESSIONS_DIR'),
|
||
app.config.get('REPORTS_DIR'),
|
||
app.config.get('CACHE_DIR'),
|
||
app.config.get('LOG_DIR'),
|
||
os.path.join(app.config.get('DATA_DIR'), 'debug') # 调试日志目录
|
||
]
|
||
|
||
for directory in directories:
|
||
if directory and not os.path.exists(directory):
|
||
os.makedirs(directory)
|
||
app.logger.info(f'创建目录: {directory}')
|
||
|
||
def init_task_manager(app):
|
||
"""初始化任务管理器"""
|
||
try:
|
||
from app.services.task_manager import task_manager
|
||
|
||
# 清理旧任务
|
||
if hasattr(task_manager, 'cleanup_old_tasks'):
|
||
cleaned = task_manager.cleanup_old_tasks(hours=24)
|
||
app.logger.info(f'清理了 {cleaned} 个旧任务')
|
||
|
||
app.logger.info('任务管理器初始化完成')
|
||
|
||
except Exception as e:
|
||
app.logger.error(f'任务管理器初始化失败: {e}')
|
||
|
||
# 导入必要的模块以避免导入错误
|
||
from flask import request
|
||
|
||
# 创建简单的错误页面模板(如果不存在)
|
||
def create_error_templates(app):
|
||
"""创建基本的错误页面模板"""
|
||
templates_dir = os.path.join(app.root_path, 'templates')
|
||
|
||
# 404页面
|
||
error_404_path = os.path.join(templates_dir, '404.html')
|
||
if not os.path.exists(error_404_path):
|
||
error_404_content = '''
|
||
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<title>404 - 页面未找到</title>
|
||
<style>
|
||
body { font-family: Arial, sans-serif; text-align: center; padding: 50px; }
|
||
h1 { color: #333; }
|
||
a { color: #007bff; text-decoration: none; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<h1>404 - 页面未找到</h1>
|
||
<p>抱歉,您访问的页面不存在。</p>
|
||
<p><a href="/">返回首页</a></p>
|
||
</body>
|
||
</html>
|
||
'''
|
||
try:
|
||
with open(error_404_path, 'w', encoding='utf-8') as f:
|
||
f.write(error_404_content)
|
||
except:
|
||
pass
|
||
|
||
# 500页面
|
||
error_500_path = os.path.join(templates_dir, '500.html')
|
||
if not os.path.exists(error_500_path):
|
||
error_500_content = '''
|
||
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<title>500 - 服务器错误</title>
|
||
<style>
|
||
body { font-family: Arial, sans-serif; text-align: center; padding: 50px; }
|
||
h1 { color: #dc3545; }
|
||
a { color: #007bff; text-decoration: none; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<h1>500 - 服务器错误</h1>
|
||
<p>抱歉,服务器遇到了一个错误。</p>
|
||
<p><a href="/">返回首页</a></p>
|
||
</body>
|
||
</html>
|
||
'''
|
||
try:
|
||
with open(error_500_path, 'w', encoding='utf-8') as f:
|
||
f.write(error_500_content)
|
||
except:
|
||
pass
|
||
|
||
# 提供一个便捷的函数来获取socketio实例
|
||
def get_socketio():
|
||
"""获取socketio实例"""
|
||
return socketio |