add /api/report-callback

This commit is contained in:
朱潮 2025-10-29 22:26:52 +08:00
parent 8583f4c607
commit 3583a50695
3 changed files with 132 additions and 98 deletions

View File

@ -0,0 +1,15 @@
meta {
name: report-callback
type: http
seq: 3
}
post {
url: http://120.26.23.172/api/report-callback
body: none
auth: inherit
}
settings {
encodeUrl: true
}

View File

@ -176,36 +176,22 @@ class ReportGenerator:
analysis_data = self.generate_analysis_text({'id': session_id})
# 调用自定义API生成报告
report_result = self.call_report_api(analysis_data)
# 构造回调URL
report_result = self.call_report_api(analysis_data, session_id)
if report_result:
# 提取学员信息用于更新报告数据
student_info = analysis_data['student_info']
report_result['studentInfo']['name'] = student_info.get('name', '未知')
report_result['studentInfo']['school'] = student_info.get('school', '未知')
report_result['studentInfo']['grade'] = student_info.get('grade', '未知')
report_result['studentInfo']['subject'] = '科学'
report_result['studentInfo']['testDate'] = get_east8_time().strftime('%Y年%m月%d')
# 构造报告数据
report_data = {
'studentInfo': report_result['studentInfo'],
'report': report_result['report'],
'generated_at': get_east8_time().isoformat(),
'session_id': session_id,
'analysis_data': analysis_data
}
# 保存报告到数据库
self.save_report_to_db(session_id, report_data, analysis_data)
if report_result and report_result.get('success'):
# API调用成功异步生成中
# 保存分析数据用于后续回调处理
self.save_analysis_data_for_regeneration(session_id, analysis_data)
return {
'success': True,
'report_data': report_data,
'message': '报告异步生成中',
'session_id': session_id,
'analysis_data': analysis_data
}
else:
raise Exception("API返回空内容")
raise Exception("API调用失败")
except Exception as e:
print(f"生成报告失败: {e}")
@ -218,87 +204,42 @@ class ReportGenerator:
'can_regenerate': True
}
def call_report_api(self, analysis_data):
def call_report_api(self, analysis_data, session_id):
"""调用自定义报告API生成报告"""
# 构建请求数据
request_data = {
"analysis_text": analysis_data['analysis_text']
"analysis_text": analysis_data['analysis_text'],
"session_id": session_id
}
# 实现重试机制
max_retries = 3
retry_delay = 2 # 秒
for attempt in range(max_retries):
try:
print(f"调用报告生成API (尝试 {attempt + 1}/{max_retries})...")
print(f"调用报告生成API...")
print(f" API端点: {self.api_url}")
print(f" Session ID: {session_id}")
print(f" 数据长度: {len(request_data['analysis_text'])} 字符")
response = requests.post(
self.api_url,
headers=self.headers,
json=request_data,
timeout=self.timeout
timeout=10 # 简化超时时间
)
if response.status_code == 200:
result = response.json()
# 验证响应格式
if 'studentInfo' in result and 'report' in result:
print(f"✅ API调用成功生成报告数据")
return result
else:
print(f"⚠️ API响应格式异常但继续处理")
print(f"✅ API调用成功已提交异步报告生成请求")
print(f" 响应内容: {str(result)[:200]}...")
return result
elif response.status_code == 401:
raise Exception("API密钥无效或已过期")
elif response.status_code == 429:
# 速率限制,增加等待时间
wait_time = retry_delay * (2 ** attempt)
print(f"API速率限制等待 {wait_time} 秒后重试...")
time.sleep(wait_time)
continue
elif response.status_code >= 500:
# 服务器错误,重试
wait_time = retry_delay * (2 ** attempt)
print(f"API服务器错误 ({response.status_code}){wait_time} 秒后重试...")
time.sleep(wait_time)
continue
return {"success": True, "message": "异步报告生成请求已提交"}
else:
raise Exception(f"API调用失败: HTTP {response.status_code} - {response.text}")
except requests.exceptions.Timeout:
wait_time = retry_delay * (2 ** attempt)
print(f"API请求超时{wait_time} 秒后重试...")
if attempt < max_retries - 1:
time.sleep(wait_time)
else:
raise Exception(f"API请求超时已达到最大重试次数 ({self.timeout}秒)")
except requests.exceptions.ConnectionError:
wait_time = retry_delay * (2 ** attempt)
print(f"API连接错误{wait_time} 秒后重试...")
if attempt < max_retries - 1:
time.sleep(wait_time)
else:
raise Exception("API连接失败已达到最大重试次数")
except Exception as e:
if attempt == max_retries - 1:
raise Exception(f"API调用失败: {str(e)}")
else:
wait_time = retry_delay * (2 ** attempt)
print(f"API调用出错: {e}{wait_time} 秒后重试...")
time.sleep(wait_time)
return None
print(f"API调用出错: {e}")
raise Exception(f"报告生成API调用失败: {str(e)}")
def save_report_to_db(self, session_id, report_data, analysis_data):
"""保存报告到数据库"""
@ -499,7 +440,7 @@ class EnhancedSurveySystem:
analysis_data = json.loads(result[0])
# 调用API生成报告
report_result = self.report_generator.call_report_api(analysis_data)
report_result = self.report_generator.call_report_api(analysis_data, session_id)
if report_result:
# 提取学员信息用于更新报告数据

80
main.py
View File

@ -14,7 +14,7 @@ from pydantic import BaseModel
from typing import Dict, List, Optional, Any
import asyncio
import threading
from enhanced_survey_system import enhanced_system, get_east8_time_string
from enhanced_survey_system import enhanced_system, get_east8_time_string, get_east8_time
app = FastAPI(title="Enhanced Survey System")
@ -49,6 +49,10 @@ class SaveAnswersRequest(BaseModel):
class GenerateReportRequest(BaseModel):
sessionId: str
class ReportCallbackRequest(BaseModel):
session_id: str
data: Dict[str, Any]
class SessionResponse(BaseModel):
success: bool
sessionId: str
@ -1030,6 +1034,80 @@ def generate_quiz_page(session_data: sqlite3.Row, session_id: str) -> str:
</body>
</html>'''
@app.post("/api/report-callback", response_model=ApiResponse)
async def report_callback(request: ReportCallbackRequest):
"""接收异步报告生成完成的回调数据"""
session_id = request.session_id
report_data = request.data
if not session_id or not report_data:
raise HTTPException(status_code=400, detail="session_id和data不能为空")
try:
# 验证会话是否存在
conn = sqlite3.connect('data/survey.db')
cursor = conn.cursor()
cursor.execute('''
SELECT id FROM quiz_sessions WHERE id = ?
''', (session_id,))
session_exists = cursor.fetchone()
if not session_exists:
conn.close()
raise HTTPException(status_code=404, detail="会话不存在")
# 获取分析数据(如果有保存的话)
cursor.execute('''
SELECT analysis_data FROM temp_analysis_data
WHERE session_id = ?
ORDER BY created_at DESC
LIMIT 1
''', (session_id,))
analysis_result = cursor.fetchone()
analysis_data = json.loads(analysis_result[0]) if analysis_result else {}
# 构造完整的报告数据
full_report_data = {
'studentInfo': report_data.get('studentInfo', {}),
'report': report_data.get('report', {}),
'generated_at': get_east8_time().isoformat(),
'session_id': session_id,
'analysis_data': analysis_data
}
# 保存报告到数据库
report_id = str(uuid.uuid4())
cursor.execute('''
INSERT INTO reports (id, session_id, report_data, analysis_data, generated_at)
VALUES (?, ?, ?, ?, ?)
''', (report_id, session_id, json.dumps(full_report_data), json.dumps(analysis_data), get_east8_time_string()))
# 更新会话状态为已完成
cursor.execute('''
UPDATE quiz_sessions
SET status = 'completed', completed_at = ?
WHERE id = ?
''', (get_east8_time_string(), session_id))
conn.commit()
conn.close()
print(f"✅ 回调处理成功: {session_id}")
print(f" 报告ID: {report_id}")
return ApiResponse(
success=True,
message='回调数据处理成功'
)
except HTTPException:
raise
except Exception as e:
print(f"❌ 回调处理失败: {e}")
raise HTTPException(status_code=500, detail=f"回调处理失败: {str(e)}")
if __name__ == "__main__":
import uvicorn
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)