- 新增后台任务API (/api/tasks) - 抓取任务在后台独立运行,不受页面刷新影响 - 支持任务状态查询和手动停止 - 新增后台任务管理界面 - 数据库新增 background_tasks 表 - 前端使用轮询方式更新任务进度
178 lines
4.3 KiB
Python
178 lines
4.3 KiB
Python
"""
|
|
后台任务 API 路由
|
|
"""
|
|
from flask import Blueprint, jsonify, request
|
|
from services.task_service import task_service
|
|
from models.database import db
|
|
import logging
|
|
|
|
logger = logging.getLogger('tasks_api')
|
|
|
|
bp = Blueprint('tasks', __name__, url_prefix='/api/tasks')
|
|
|
|
|
|
@bp.route('/start', methods=['POST'])
|
|
def start_task():
|
|
"""
|
|
启动后台抓取任务
|
|
|
|
请求体:
|
|
{
|
|
"results": [{"title": "...", "url": "..."}, ...],
|
|
"auto_save": true,
|
|
"category": "AI模型",
|
|
"keywords": ["关键词1", "关键词2"]
|
|
}
|
|
"""
|
|
try:
|
|
data = request.get_json()
|
|
|
|
if not data or 'results' not in data:
|
|
return jsonify({
|
|
'success': False,
|
|
'error': '缺少 results 参数'
|
|
}), 400
|
|
|
|
results = data.get('results', [])
|
|
auto_save = data.get('auto_save', False)
|
|
category = data.get('category', '')
|
|
keywords = data.get('keywords', [])
|
|
|
|
if not results:
|
|
return jsonify({
|
|
'success': False,
|
|
'error': '结果列表为空'
|
|
}), 400
|
|
|
|
# 启动后台任务
|
|
task_id = task_service.start_fetch_task(
|
|
results=results,
|
|
auto_save=auto_save,
|
|
category=category,
|
|
keywords=keywords
|
|
)
|
|
|
|
return jsonify({
|
|
'success': True,
|
|
'task_id': task_id,
|
|
'message': f'任务已启动,共 {len(results)} 个URL'
|
|
})
|
|
|
|
except Exception as e:
|
|
logger.error(f"启动任务失败: {e}")
|
|
return jsonify({
|
|
'success': False,
|
|
'error': str(e)
|
|
}), 500
|
|
|
|
|
|
@bp.route('/<task_id>/status', methods=['GET'])
|
|
def get_task_status(task_id):
|
|
"""获取任务状态"""
|
|
task = task_service.get_task_status(task_id)
|
|
|
|
if not task:
|
|
return jsonify({
|
|
'success': False,
|
|
'error': '任务不存在'
|
|
}), 404
|
|
|
|
return jsonify({
|
|
'success': True,
|
|
'task': task
|
|
})
|
|
|
|
|
|
@bp.route('/<task_id>/stop', methods=['POST'])
|
|
def stop_task(task_id):
|
|
"""停止任务"""
|
|
task = db.get_task(task_id)
|
|
|
|
if not task:
|
|
return jsonify({
|
|
'success': False,
|
|
'error': '任务不存在'
|
|
}), 404
|
|
|
|
if task['status'] not in ('pending', 'running'):
|
|
return jsonify({
|
|
'success': False,
|
|
'error': '任务已完成或已停止'
|
|
}), 400
|
|
|
|
# 设置停止标志
|
|
if task_service.stop_task(task_id):
|
|
return jsonify({
|
|
'success': True,
|
|
'message': '已请求停止任务'
|
|
})
|
|
else:
|
|
return jsonify({
|
|
'success': False,
|
|
'error': '停止任务失败'
|
|
}), 500
|
|
|
|
|
|
@bp.route('/active', methods=['GET'])
|
|
def get_active_tasks():
|
|
"""获取活动任务列表"""
|
|
tasks = task_service.get_active_tasks()
|
|
|
|
return jsonify({
|
|
'success': True,
|
|
'tasks': tasks,
|
|
'count': len(tasks)
|
|
})
|
|
|
|
|
|
@bp.route('/recent', methods=['GET'])
|
|
def get_recent_tasks():
|
|
"""获取最近的任务"""
|
|
limit = request.args.get('limit', 20, type=int)
|
|
tasks = db.get_recent_tasks(limit)
|
|
|
|
return jsonify({
|
|
'success': True,
|
|
'tasks': tasks,
|
|
'count': len(tasks)
|
|
})
|
|
|
|
|
|
@bp.route('/<task_id>', methods=['DELETE'])
|
|
def delete_task(task_id):
|
|
"""删除任务记录"""
|
|
task = db.get_task(task_id)
|
|
|
|
if not task:
|
|
return jsonify({
|
|
'success': False,
|
|
'error': '任务不存在'
|
|
}), 404
|
|
|
|
if task['status'] in ('pending', 'running'):
|
|
return jsonify({
|
|
'success': False,
|
|
'error': '任务仍在运行,请先停止'
|
|
}), 400
|
|
|
|
if db.delete_task(task_id):
|
|
return jsonify({
|
|
'success': True,
|
|
'message': '任务已删除'
|
|
})
|
|
else:
|
|
return jsonify({
|
|
'success': False,
|
|
'error': '删除失败'
|
|
}), 500
|
|
|
|
|
|
@bp.route('/clear', methods=['POST'])
|
|
def clear_completed_tasks():
|
|
"""清理已完成的任务"""
|
|
count = db.clear_completed_tasks()
|
|
|
|
return jsonify({
|
|
'success': True,
|
|
'message': f'已清理 {count} 个任务'
|
|
}) |