前两天吃饭,一个当班主任的朋友跟我吐槽,期末发成绩差点没把他折腾死。全班48个人,一个人在微信上挨个私发,发到晚上十点还没发完;后来干脆把Excel丢群里,第二天就有家长私聊质问“为什么排名这么靠后”。他问我:有没有一种办法,成绩能发,但每个人只能看到自己的?我用一个空文件加一段脚本,十分钟给他拼出一个简单的查询页面。他拿过去试了试,把自己的Excel成绩单复制进模板,改两行说明文字,保存,发到家长群——整个过程用不了半分钟。今天就把这个工具和背后的思考完整拆出来。
这个工具本质上是一个单文件HTML网页,双击就能在浏览器里打开,学生或家长输入学号或姓名,页面只显示学生本人的成绩记录。不装软件、不搭服务器、不注册账号,对非技术背景的老师来说,门槛几乎为零。适用场景也不止期末成绩发布:体育比赛结果查询、培训考核公示、企业内部技能认证、竞赛入围名单,凡是“发Excel会泄露隐私、逐个私发又太累”的事情,都可以套这个模板。下面我按“为什么这样做、原理是什么、代码怎么用、怎么发出去、踩过哪些坑”的顺序,完整写一遍。
1. 发个成绩,怎么就成了老师和家长的共同烦恼
1.1 传统发成绩的三个致命痛点
先说效率。一个班四五十人,用微信或者短信逐个私发,哪怕每个学生只发一条“姓名+成绩+排名”,操作上也要经历“找到聊天窗口、粘贴、发送”三个动作,平均一个人20秒打底,四五十人就是十五到二十分钟起步,遇到要解释两句的,半小时直接打不住。这还只是一个班,班主任如果带两个班,时间直接翻倍。
再说隐私。在微信群里丢一份Excel或者PDF,全班成绩一览无余。表面上是“公开透明”,实际上非常容易引发矛盾:排名靠后的家长会觉得自己孩子被“示众”了,个别家长还会拿别人家孩子的成绩来做对比,甚至截图发到别的群里。这类事情一旦发酵,老师后面的工作会非常被动。
最后是操作门槛。有人会说,用腾讯文档、WPS在线表格不就行了?设置“仅查看”权限、指定链接、指定人员,理论上确实能解决。但实际操作中,家长需要点链接、登录账号、同意授权,折腾一圈下来,群里又要多几十条“怎么打不开”“怎么要验证码”的提问。很多老师本来就不太熟悉这些工具的权限设置,一着急把编辑权限也打开了,结果更乱。
1.2 单文件查询页为什么正好踩中需求
我当时的判断是:这个场景不需要“系统”,只需要一个“查询页面”。
所谓系统,意味着要有用户名密码、要处理并发、要有数据库,这是给全校几千人准备的东西。而一个普通班级或者一个培训班,核心诉求就两点:一是数据能发出去,二是每个人只能看到自己的。用单个HTML文件完全可以做到。
这个文件打开就是网页,不需要安装任何软件;数据直接和文件一起打包,发给别人就能用,对方也不需要访问任何平台;查询时只把匹配到的那一条记录显示出来,天然满足“一人一结果”的效果。更关键的是,整个过程中成绩数据没有上传到任何第三方服务器,文件在谁手里,数据就在谁手里,这对于老师来说是可控的。
1.3 “30秒”是怎么算出来的
这里要坦白一下:30秒不是从零写代码的时间,而是“把模板变成自己可用的工具”的时间。
我第一次做这个模板的时候,写代码花了十分钟,但那是开发者的事。当老师拿到模板后,他要做的事情只有三步:
- 打开自己的Excel成绩表,全选复制;
- 打开模板HTML文件,在代码里找到成绩数据区,粘贴覆盖;
- 保存文件,发到家长群。
这三步手快一点,30秒真能完成。后面我会把整个数据替换过程一步步写清楚,你照着操作一遍就知道,真不需要懂代码。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 原理拆解:一个HTML文件为什么能完成查询
2.1 数据格式的选择:CSV比JSON更适合非程序员
要让网页能查询成绩,首先得让成绩数据能被JavaScript读取。常见的做法是在代码里写一组JSON格式的数据,类似这样:
json复制[
{ "学号": "20240101", "姓名": "张同学", "语文": 96 },
{ "学号": "20240102", "姓名": "李同学", "语文": 82 }
]
这个格式本身没问题,但让一个非程序员从Excel复制出来,再手工改成JSON,每次都要加引号、加花括号、加逗号,错一个符号页面就跑不起来,这对老师来说太不友好了。
所以我换成了CSV格式,说白了就是纯文本的表格,用逗号分隔每一列,用换行分隔每一行。Excel里复制一个区域,粘贴进来就是这个格式。老师在代码里看到的数据,跟他自己表格里的行列结构完全一致,不需要任何转换。
2.2 解析、匹配、渲染三步走
整个查询过程拆开来看,就是三步。
第一步是解析:JavaScript把那段CSV文本按换行拆成一行一条,再按逗号拆成一个个字段;第一行作为表头,也就是字段名,后面每一行拼成一个对象。这一步调用的就是代码里的parseScore函数。
第二步是匹配:用户在输入框里输
