Files

203 lines
7.1 KiB
HTML
Raw Permalink Normal View History

2026-06-24 13:11:34 +08:00
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>问卷汇总报告 — 天恒高考志愿</title>
<link rel="stylesheet" href="/css/style.css">
<style>
.summary-container { max-width: 900px; margin: 0 auto; }
.section-card {
background: var(--card);
border-radius: var(--radius-md);
padding: 20px 24px;
margin: 16px 0;
box-shadow: var(--shadow-sm);
border-left: 4px solid var(--navy-500);
}
.section-card.parents { border-left-color: var(--amber); }
.section-card h3 { font-size: 16px; color: var(--navy-700); margin-bottom: 12px; }
.qa-item {
margin: 8px 0;
padding: 8px 0;
border-bottom: 1px solid var(--border);
}
.qa-item:last-child { border-bottom: none; }
.qa-item .label { font-size: 12px; color: var(--text-muted); }
.qa-item .value { font-size: 14px; color: var(--text); margin-top: 2px; }
.standalone-card {
display: inline-block;
background: var(--navy-light);
border-radius: var(--radius-md);
padding: 16px 20px;
margin: 8px;
text-align: center;
min-width: 140px;
}
.standalone-card .type { font-size: 28px; font-weight: 900; color: var(--navy-600); letter-spacing: 2px; }
.standalone-card .label { font-size: 12px; color: var(--text-muted); margin-top: 4px; }
.btn-row { display: flex; gap: 10px; flex-wrap: wrap; margin: 20px 0; justify-content: center; }
.empty-note {
color: var(--text-muted);
font-size: 13px;
font-style: italic;
}
@media print {
.top-bar, .btn-row, .back-link { display: none; }
.summary-container { max-width: 100%; }
body { background: white; }
}
</style>
</head>
<body>
<div class="top-bar">
DOCUMENT ID: ZJ-2026-TH-001 &nbsp;|&nbsp; 仅供家庭成员查阅
</div>
<div class="container summary-container">
<div style="margin:20px 0;">
<a href="/" style="color:var(--navy-600);text-decoration:none;font-size:13px;font-weight:600;">← 返回首页</a>
&nbsp;|&nbsp;
<a href="/dashboard.html" style="color:var(--navy-600);text-decoration:none;font-size:13px;font-weight:600;">📋 完成情况</a>
</div>
<div class="hero" style="padding:24px 20px 20px;">
<h1>📄 问卷汇总报告</h1>
<p class="sub">6项测评结果综合概览 · 家庭参考文档</p>
</div>
<div class="alert alert-info" id="completionAlert" style="display:none;">
⚠️ 部分测评尚未完成,以下仅展示已提交的结果。
</div>
<!-- 独立测评结果 -->
<h2 style="font-size:18px;color:var(--navy-700);margin:20px 0 0;">🧪 自评测试结果</h2>
<div id="standaloneResults" style="margin:12px 0;">
<p class="empty-note">加载中...</p>
</div>
<!-- API问卷结果 -->
<h2 style="font-size:18px;color:var(--navy-700);margin:20px 0 0;">📝 线上问卷结果</h2>
<div id="questionnaireResults">
<p class="empty-note">加载中...</p>
</div>
<!-- 操作按钮 -->
<div class="btn-row">
<button class="btn btn-primary" onclick="window.print()">🖨️ 打印报告</button>
<a href="/dashboard.html" class="btn btn-outline">📋 查看完成状态</a>
<a href="/" class="btn btn-outline">🏠 返回首页</a>
</div>
<div style="font-size:11px;color:var(--text-muted);text-align:center;margin:20px 0;" id="genTime"></div>
</div>
<script>
(async function() {
try {
const resp = await fetch('/api/summary');
const data = await resp.json();
renderSummary(data);
} catch(e) {
document.getElementById('standaloneResults').innerHTML =
'<div class="alert alert-amber">无法连接后端服务,请确保 Flask 已启动</div>';
document.getElementById('questionnaireResults').innerHTML = '';
}
})();
function renderSummary(data) {
// 完成度提示
if (data.status.completed < data.status.total) {
document.getElementById('completionAlert').style.display = 'block';
document.getElementById('completionAlert').textContent =
'⚠️ 仅 ' + data.status.completed + '/' + data.status.total + ' 项测评已完成,以下为当前已提交结果。请填写剩余问卷后刷新。';
}
// 独立测评
const std = data.standalone_tests || {};
let stdHtml = '';
const testMeta = {
holland: { name: '霍兰德职业兴趣测试', icon: '🔬' },
mbti: { name: 'MBTI 性格测试', icon: '🧠' }
};
for (const [key, meta] of Object.entries(testMeta)) {
const s = std[key];
if (s) {
stdHtml += `<div class="standalone-card">
<div style="font-size:12px;color:var(--text-muted);">${meta.icon} ${meta.name}</div>
<div class="type">${s.result}</div>
<div class="label">${s.user_name} · ${s.completed_at || ''}</div>
</div>`;
} else {
stdHtml += `<div class="standalone-card" style="opacity:0.5;">
<div style="font-size:12px;color:var(--text-muted);">${meta.icon} ${meta.name}</div>
<div class="type">—</div>
<div class="label">未提交</div>
</div>`;
}
}
document.getElementById('standaloneResults').innerHTML = stdHtml || '<p class="empty-note">暂无独立测评结果</p>';
// API问卷
const qs = data.questionnaires || [];
let qHtml = '';
qs.forEach(q => {
const borderClass = q.target_user === '父母' ? ' parents' : '';
const tagBadge = q.target_user === '父母'
? '<span class="badge badge-amber" style="margin-left:8px;">父母填写</span>'
: '<span class="badge badge-blue" style="margin-left:8px;">天恒填写</span>';
if (q.responses && q.responses.length > 0) {
const responses = q.responses;
qHtml += `<div class="section-card${borderClass}">
<h3>${q.title} ${tagBadge} <span style="font-weight:400;font-size:12px;color:var(--text-muted);">${responses.length} 份答卷)</span></h3>`;
responses.forEach((r, ri) => {
const answers = r.answers || {};
qHtml += `<div style="margin:12px 0;padding:10px;background:var(--bg);border-radius:6px;">
<div style="font-weight:600;font-size:13px;margin-bottom:6px;">👤 ${r.user_name} <span style="font-weight:400;font-size:11px;color:var(--text-muted);">${r.created_at}</span></div>`;
Object.entries(answers).forEach(([key, val], vi) => {
if (vi < 10) { // 最多显示10条
qHtml += `<div class="qa-item">
<div class="label">Q${key}:</div>
<div class="value">${escapeHtml(String(val))}</div>
</div>`;
}
});
if (Object.keys(answers).length > 10) {
qHtml += `<div style="font-size:12px;color:var(--text-muted);">... 共 ${Object.keys(answers).length} 题</div>`;
}
qHtml += '</div>';
});
qHtml += '</div>';
} else {
qHtml += `<div class="section-card${borderClass}" style="opacity:0.6;">
<h3>${q.title} ${tagBadge}</h3>
<p class="empty-note">暂无答卷</p>
</div>`;
}
});
document.getElementById('questionnaireResults').innerHTML = qHtml || '<p class="empty-note">暂无问卷结果</p>';
// 生成时间
document.getElementById('genTime').textContent = '报告生成时间:' + (data.generated_at || '');
}
function escapeHtml(str) {
const div = document.createElement('div');
div.textContent = str;
return div.innerHTML;
}
</script>
</body>
</html>