Files
simon b6df028839 v1.0.0 高考志愿门户完整修复
变更摘要:
- [fix] 清理根目录 index.html 遗留代码(questionnaire-error + retryLoad 移除)
- [fix] 副标题同步更新为自估591分 + 候选志愿546条数据校准
- [fix] 页脚注入版本号 v1.0.0
- [fix] 部署版 index.html: 取消家长标签,统一 filler-tianheng
- [fix] Dashboard 文案修正(4份→2份线上问卷)
- [fix] 清理冗余部署脚本(v1-v4归档至 archived_scripts/)
- [fix] 等效位次工具纳入 deploy 目录
- [chore] .gitignore 初始化
- [init] Git 仓库初始化
2026-06-24 13:11:34 +08:00

284 lines
8.6 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!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>
/* 汇总页特有样式 */
.member-card {
background: var(--card);
border-radius: var(--radius);
padding: 20px;
margin-bottom: 16px;
border: 1px solid var(--border);
}
.member-card h3 {
font-size: 16px;
color: var(--blue);
margin-bottom: 4px;
}
.member-card .time {
font-size: 12px;
color: var(--text-muted);
margin-bottom: 12px;
}
.answer-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 8px;
}
.answer-item {
padding: 8px 12px;
background: var(--bg);
border-radius: 6px;
font-size: 13px;
}
.answer-item .q-label {
color: var(--text-muted);
font-size: 11px;
margin-bottom: 2px;
}
.answer-item .q-val {
font-weight: 600;
color: var(--text);
}
.highlight-diff {
background: #FFF3E0;
border-left: 3px solid var(--amber);
}
.empty-state {
text-align: center;
padding: 40px 0;
color: var(--text-muted);
}
/* 对比表格 */
.compare-table {
width: 100%;
border-collapse: collapse;
font-size: 13px;
margin-top: 12px;
}
.compare-table th {
background: var(--blue-light);
padding: 10px 12px;
text-align: left;
font-weight: 600;
font-size: 12px;
}
.compare-table td {
padding: 10px 12px;
border-bottom: 1px solid var(--border);
vertical-align: top;
}
.compare-table tr:hover td {
background: #fafbfc;
}
</style>
</head>
<body>
<div class="container">
<div id="app">
<div id="loading" style="text-align:center;padding:60px;">
<p style="color:var(--text-muted);">加载汇总数据...</p>
</div>
</div>
</div>
<script>
// ============================================================
// 问卷结果汇总页 — 展示所有成员的答卷,并高亮差异
// ============================================================
const params = new URLSearchParams(window.location.search);
const qid = params.get('id');
if (!qid) {
document.getElementById('app').innerHTML =
'<div style="text-align:center;padding:60px;"><p style="color:var(--red);">缺少问卷ID</p><a href="/" class="btn btn-primary" style="margin-top:16px;">← 返回首页</a></div>';
} else {
loadResults(qid);
}
async function loadResults(qid) {
try {
// 并行加载问卷信息和答案
const [qResp, rResp] = await Promise.all([
fetch(`/api/questionnaire/${qid}`),
fetch(`/api/results/${qid}`)
]);
if (!qResp.ok) throw new Error('问卷不存在');
const questionnaire = await qResp.json();
const results = await rResp.json();
let html = `
<div style="margin-bottom:20px;display:flex;justify-content:space-between;align-items:center;">
<a href="/" style="color:var(--blue);text-decoration:none;font-size:13px;">← 返回首页</a>
<a href="/questionnaire.html?id=${qid}" class="btn btn-outline btn-sm">📝 我也填一份</a>
</div>
<div class="hero" style="padding:20px 0 16px;">
<h1>📊 ${questionnaire.title} · 汇总</h1>
<p class="sub">共 ${results.length} 份答卷</p>
</div>
`;
if (results.length === 0) {
html += '<div class="empty-state"><p>📭 还没有人填写这份问卷</p><a href="/questionnaire.html?id=' + qid + '" class="btn btn-primary" style="margin-top:16px;">✍️ 我来填第一份</a></div>';
} else {
// 判断问卷类型,选择合适的展示方式
const qData = questionnaire.questions;
if (qData.type === 'likert') {
// Holland 评估:按维度汇总得分
html += renderHollandSummary(qData, results);
} else {
// 普通选择题问卷:横向对比表格
html += renderComparisonTable(qData, results);
}
}
document.getElementById('app').innerHTML = html;
} catch (err) {
document.getElementById('app').innerHTML = `
<div style="text-align:center;padding:60px;">
<p style="color:var(--red);">加载失败:${err.message}</p>
<a href="/" class="btn btn-primary" style="margin-top:16px;">← 返回首页</a>
</div>`;
}
}
// ============ Holland 评估:雷达图 + 维度得分表 ============
function renderHollandSummary(qData, results) {
const dims = qData.dimensions;
const dimNames = { R: '现实型', I: '研究型', A: '艺术型', S: '社会型', E: '企业型', C: '常规型' };
const dimDescs = {
R: '动手操作·机械·户外',
I: '分析思考·科学·研究',
A: '创造表达·艺术·审美',
S: '助人教学·沟通·服务',
E: '领导说服·管理·商业',
C: '秩序规范·数据·流程'
};
let html = '<div class="section-title">🎯 各维度得分对比</div>';
// 每个人一行卡片
results.forEach(r => {
// 按维度汇总得分
const scores = {};
dims.forEach(d => { scores[d] = 0; });
let count = {};
Object.entries(r.answers).forEach(([qid, val]) => {
const item = qData.items.find(i => i.id === qid);
if (item) {
scores[item.dimension] = (scores[item.dimension] || 0) + parseInt(val);
count[item.dimension] = (count[item.dimension] || 0) + 1;
}
});
// 算平均分
dims.forEach(d => {
scores[d] = count[d] ? (scores[d] / count[d]).toFixed(1) : 0;
});
// 找出最高分维度(前2
const sorted = dims.map(d => ({ dim: d, score: parseFloat(scores[d]) }))
.sort((a, b) => b.score - a.score);
const top2 = sorted.slice(0, 2);
html += `
<div class="member-card">
<h3>👤 ${r.user_name}</h3>
<p class="time">提交时间:${r.created_at}</p>
<p style="font-size:14px;margin-bottom:12px;">
🏆 主导类型:<strong>${dimNames[top2[0].dim]}${top2[0].score}分)</strong>、
${dimNames[top2[1].dim]}${top2[1].score}分)
</p>
<table class="compare-table">
<tr>
${dims.map(d => `<th>${dimNames[d]}<br><span style="font-weight:400;font-size:10px;">${dimDescs[d]}</span></th>`).join('')}
</tr>
<tr>
${dims.map(d => {
const score = parseFloat(scores[d]);
const isTop = top2.some(t => t.dim === d);
return `<td style="text-align:center;${isTop ? 'font-weight:700;color:var(--blue);' : ''}">
${'⭐'.repeat(Math.round(score))}<br>${scores[d]}
</td>`;
}).join('')}
</tr>
</table>
</div>
`;
});
return html;
}
// ============ 普通问卷:横向对比表格 ============
function renderComparisonTable(qData, results) {
let html = '<div class="section-title">📋 逐题对比</div>';
// 构建对比表格:行=题目,列=成员
const members = results.map(r => r.user_name);
const memberAnswers = {};
results.forEach(r => {
memberAnswers[r.user_name] = r.answers;
});
html += '<div style="overflow-x:auto;">';
html += '<table class="compare-table">';
html += '<tr><th style="min-width:40px;">#</th><th style="min-width:200px;">题目</th>';
members.forEach(m => {
html += `<th style="min-width:150px;">${m}</th>`;
});
html += '</tr>';
qData.forEach((q, idx) => {
// 检查所有成员的答案是否一致
const values = members.map(m => memberAnswers[m] ? memberAnswers[m][q.id] || '-' : '-');
const allSame = values.every(v => v === values[0] && v !== '-');
const someBlank = values.some(v => v === '-');
html += `<tr class="${!allSame && !someBlank ? 'highlight-diff' : ''}">`;
html += `<td>${idx + 1}</td>`;
html += `<td style="font-size:12px;">${q.text}</td>`;
members.forEach(m => {
const val = memberAnswers[m] ? (memberAnswers[m][q.id] || '-') : '-';
// 把选项值映射为标签
let display = val;
if (q.options && val !== '-') {
const vals = val.split(',');
display = vals.map(v => {
const opt = q.options.find(o => o.value === v.trim());
return opt ? opt.label : v;
}).join('、');
}
html += `<td>${display}</td>`;
});
html += '</tr>';
});
html += '</table></div>';
// 差异提示
html += `
<div style="background:#FFF3E0;border-radius:8px;padding:12px 16px;margin-top:16px;font-size:13px;color:var(--amber);">
💡 橙色高亮行 = 家人之间答案不一致的题目。这些差异点建议在填报前专门讨论,达成共识。
</div>
`;
return html;
}
</script>
</body>
</html>