修改展示页面

This commit is contained in:
朱潮 2025-10-30 00:34:56 +08:00
parent 6313d7c63a
commit 871b4baadc

266
main.py
View File

@ -471,7 +471,7 @@ async def quiz_page(session_id: str, request: Request):
cursor = conn.cursor() cursor = conn.cursor()
cursor.execute(''' cursor.execute('''
SELECT s.*, qs.questions_config, qs.status SELECT s.*, qs.questions_config, qs.status, qs.total_score, qs.completed_at
FROM students s FROM students s
JOIN quiz_sessions qs ON s.id = qs.student_id JOIN quiz_sessions qs ON s.id = qs.student_id
WHERE qs.id = ? WHERE qs.id = ?
@ -483,7 +483,12 @@ async def quiz_page(session_id: str, request: Request):
if not session_data: if not session_data:
raise HTTPException(status_code=404, detail="Session not found") raise HTTPException(status_code=404, detail="Session not found")
# 生成答题页面HTML # 检查会话状态
if session_data['status'] in ['completed', 'can_regenerate']:
# 显示完成状态页面
html_content = generate_completion_page(session_data, session_id)
else:
# 显示答题页面
html_content = generate_quiz_page(session_data, session_id) html_content = generate_quiz_page(session_data, session_id)
return Response(content=html_content, media_type="text/html; charset=utf-8") return Response(content=html_content, media_type="text/html; charset=utf-8")
@ -1095,6 +1100,263 @@ async def report_callback(request: ReportCallbackRequest):
print(f"❌ 回调处理失败: {e}") print(f"❌ 回调处理失败: {e}")
raise HTTPException(status_code=500, detail=f"回调处理失败: {str(e)}") raise HTTPException(status_code=500, detail=f"回调处理失败: {str(e)}")
def generate_completion_page(session_data: sqlite3.Row, session_id: str) -> str:
"""生成答题完成页面HTML"""
student_name = session_data['name']
school = session_data['school']
grade = session_data['grade']
total_score = session_data['total_score'] or 0
completed_at = session_data['completed_at'] or '未知时间'
return f'''<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{student_name} - 测评已完成</title>
<style>
* {{
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Microsoft YaHei', sans-serif;
}}
body {{
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}}
.container {{
background: white;
border-radius: 20px;
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
padding: 40px;
text-align: center;
max-width: 600px;
width: 100%;
}}
.success-icon {{
width: 80px;
height: 80px;
background: linear-gradient(135deg, #4CAF50, #45a049);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto 30px;
font-size: 40px;
color: white;
}}
h1 {{
color: #333;
margin-bottom: 20px;
font-size: 28px;
}}
.student-info {{
background: #f8f9fa;
padding: 20px;
border-radius: 10px;
margin: 20px 0;
text-align: left;
}}
.info-row {{
display: flex;
justify-content: space-between;
margin: 10px 0;
padding: 5px 0;
border-bottom: 1px solid #eee;
}}
.info-row:last-child {{
border-bottom: none;
}}
.info-label {{
font-weight: bold;
color: #666;
}}
.info-value {{
color: #333;
}}
.score-display {{
background: linear-gradient(135deg, #FF6B6B, #4ECDC4);
color: white;
padding: 30px;
border-radius: 15px;
margin: 30px 0;
position: relative;
overflow: hidden;
}}
.score-display::before {{
content: '';
position: absolute;
top: -50%;
right: -50%;
width: 200%;
height: 200%;
background: rgba(255,255,255,0.1);
transform: rotate(45deg);
}}
.score-number {{
font-size: 48px;
font-weight: bold;
margin-bottom: 10px;
position: relative;
z-index: 1;
}}
.score-label {{
font-size: 18px;
opacity: 0.9;
position: relative;
z-index: 1;
}}
.message {{
color: #666;
font-size: 16px;
margin: 20px 0;
line-height: 1.6;
}}
.actions {{
margin-top: 30px;
}}
.btn {{
display: inline-block;
padding: 12px 30px;
margin: 10px;
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
text-decoration: none;
border-radius: 25px;
font-weight: bold;
transition: all 0.3s ease;
border: none;
cursor: pointer;
}}
.btn:hover {{
transform: translateY(-2px);
box-shadow: 0 10px 20px rgba(102, 126, 234, 0.3);
}}
.btn-secondary {{
background: linear-gradient(135deg, #6c757d, #5a6268);
}}
.footer {{
margin-top: 40px;
padding-top: 20px;
border-top: 1px solid #eee;
color: #999;
font-size: 14px;
}}
@media (max-width: 768px) {{
.container {{
padding: 20px;
}}
h1 {{
font-size: 24px;
}}
.score-number {{
font-size: 36px;
}}
.btn {{
display: block;
margin: 10px auto;
width: 80%;
}}
}}
</style>
</head>
<body>
<div class="container">
<div class="success-icon"></div>
<h1>测评已完成</h1>
<div class="student-info">
<div class="info-row">
<span class="info-label">姓名</span>
<span class="info-value">{student_name}</span>
</div>
<div class="info-row">
<span class="info-label">学校</span>
<span class="info-value">{school}</span>
</div>
<div class="info-row">
<span class="info-label">年级</span>
<span class="info-value">{grade}</span>
</div>
<div class="info-row">
<span class="info-label">完成时间</span>
<span class="info-value">{completed_at}</span>
</div>
</div>
<div class="score-display">
<div class="score-number">{total_score} </div>
<div class="score-label">本次测评得分</div>
</div>
<div class="message">
恭喜您完成了本次学科能力测评<br>
系统正在为您生成详细的个性化报告请稍后查看
</div>
<div class="actions">
<a href="/" class="btn">返回首页</a>
<button onclick="checkAndShowReport('{session_id}')" class="btn btn-secondary">查看报告</button>
</div>
<script>
async function checkAndShowReport(sessionId) {{
try {{
// 首先尝试通过session_id查找报告
const response = await fetch('/api/reports');
const data = await response.json();
const report = data.reports.find(r => r.session_id === sessionId);
if (report) {{
// 找到报告跳转到报告页面
window.location.href = `/report.html?id=${{report.id}}`;
}} else {{
// 报告还在生成中显示提示
alert('报告正在生成中,请稍后再试。\\\\n您也可以稍后返回首页查看历史报告。');
}}
}} catch (error) {{
console.error('检查报告失败:', error);
alert('检查报告状态失败,请稍后再试。');
}}
}}
</script>
<div class="footer">
学科能力测评系统 | 专业 · 科学 · 个性化
</div>
</div>
</body>
</html>'''
if __name__ == "__main__": if __name__ == "__main__":
import uvicorn import uvicorn
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True) uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)