纯HTML+JS可实现单页心理测评:通过name分组单选、data-score绑定加权分,JS汇总计算;反向题用预映射避免eval;结果页用scoreRanges对象匹配区间返回专业解释,无需后端。

如何用纯 HTML + JavaScript 实现心理量表的答题与结果计算
不需要后端、不依赖框架,一个 index.html 文件就能跑通「单页面心理测评」:题目展示 → 用户作答 → 提交后即时算分 → 显示维度解释。核心在于用 data-score 绑定选项分值,用 name 分组控制单选逻辑,再用 JS 汇总所有题目的选中值。
常见错误是把每道题写成独立表单(导致无法统一提交),或用 id 而非 name 管理单选组(用户只能选一题里的一项,但跨题无法隔离)。正确做法是:每道题用唯一 name="q1"、name="q2"…,每个选项用 value 存原始分(如 0/1/2),再通过 data-score 存加权分(如反向计分题需映射为 2/1/0)。
- 示例题干:
<div class="item"> <p>我经常感到疲惫</p> <label><input type="radio" name="q1" value="0" data-score="0">从不</label><label><input type="radio" name="q2" value="1" data-score="1">偶尔</label> </div> - 反向题处理:第 5 题若为反向条目,可写
<input ... data-score="3-value">,JS 中用eval()或提前映射(更安全) - 提交按钮绑定
onclick="calculateScore()",避免用<form></form>默认跳转
如何让量表结果页显示专业解释而非干巴巴的数字
单纯返回总分(如“你的焦虑得分为 18”)没有临床意义。必须关联常模或维度定义。做法是在 JS 里硬编码一个 scoreRanges 对象,键为量表名称,值为分段描述数组,按分数区间匹配。
立即学习“前端免费学习笔记(深入)”;
例如 GAD-7 量表:0–4 为“无症状”,5–9 为“轻度”,10–14 为“中度”,≥15 为“重度”。不要用 if-else 堆砌,改用循环比对:
const GAD7_RANGES = [
{ min: 0, max: 4, text: "未见明显焦虑症状" },
{ min: 5, max: 9, text: "可能存在轻度焦虑,建议关注情绪变化" },
{ min: 10, max: 14, text: "中度焦虑,可考虑心理咨询支持" },
{ min: 15, max: 21, text: "重度焦虑,建议尽快联系精神科或临床心理师" }
];
function getInterpretation(score) {
return GAD7_RANGES.find(r => score >= r.min && score <= r.max)?.text || "分数异常";
}
- 务必检查
find()返回undefined的情况,否则?.text会报错 - 如果量表含多个维度(如 PHQ-9 的情绪/认知/躯体子量表),每个维度单独建
scoreRanges对象,别混在一起 - 避免在 HTML 中直接拼接解释文案(不利于多语言或后续修改),全部由 JS 控制输出
为什么本地打开 HTML 文件时,Chrome 会阻止 localStorage 写入
当你双击打开 index.html,地址栏显示 file:///xxx/index.html,此时 Chrome 出于安全策略禁用 localStorage(报错 SecurityError: Failed to read the 'localStorage' property)。这不是代码问题,是浏览器限制。
- 临时解决:用
python3 -m http.server 8000启一个本地服务,然后访问http://localhost:8000 - 长期方案:所有数据存在内存对象(
let answers = {})中,不依赖持久化——适合一次性测评场景 - 若真要存档,改用
sessionStorage(页面关闭即清空)或引导用户下载 JSON 文件(用Blob+a.download)
移动端适配最该做的三件事
心理测评页面在手机上卡顿、点不准、文字挤成一团,往往不是响应式写得不够细,而是忽略了三个基础点:
- 强制设置
<meta name="viewport" content="width=device-width, initial-scale=1">,否则 iOS Safari 默认缩放为桌面视口 - 所有
<input type="radio">必须包裹在<label></label>内,且label设置display: block和足够内边距(至少padding: 12px),否则手指点击区域太小 - 禁用用户缩放:
<meta name="viewport" content="..., user-scalable=no">——防止误操作放大页面导致布局错乱(尤其对老年用户友好)
复杂点在于不同量表的计分规则差异极大:有的正向计分,有的反向,有的混合;有的按总分判级,有的看某几题组合模式。这些逻辑必须在 JS 层清晰分离,不能靠 HTML 结构暗示。容易被忽略的是“跳题逻辑”——比如 PHQ-9 第 1 题选“完全不会”,后续问题应隐藏。这需要额外监听并切换 display,不是基础实现范围,但上线前务必确认是否需要。


















