功能介绍
-
老师登录 + 访客浏览
老师账号在 data/config.json 预设,登录后可管理自己创建的所有班级;访客(学生/家长)在「学生查询」页输入学号或扫自己本子上的二维码,只能看到该学生自己的作业情况。
-
班级 → 学科 → 学生
创建班级(一级)、学科(二级)、添加学生(三级,姓名+学号);学生可调班。
-
二维码贴纸 PDF
按 班级+学科 生成每位学生的加密二维码,A4 每页 6×8=48 张,码下带姓名/学号,裁剪线清晰,打印后贴到学生本子上。二维码内容为加密后的「V1|班级|学科|学号」,只有配置了相同密钥的系统能解密。
-
扫码收作业
老师发起作业后,在作业页用浏览器摄像头批量/单次扫码。扫码成功自动标记“已上交”并全屏+声音反馈;重复扫码有明确提示且不重复计数;也可手动输入学号或点击名单状态快速改为 未交/已上交/已完成。
-
报表统计
① 作业报表——某个作业谁没交(未交名单);
② 按学科统计——各学科作业数、上交率;
③ 按学生统计——每个学生应交/已交/完成率和排名。
安装与运行
要求 Python 3.9+(已在 3.11 验证)。
pip install -r requirements.txt
python app.py
启动后访问:
http://localhost:5098
局域网内手机访问:
http://本机IP:5098
默认账号:admin / 123456
演示账号:demo / 123456
部署到有公网域名的服务器时,建议在服务器端用 Nginx/Caddy 等配置 HTTPS(见下方摄像头说明)。
首次部署请务必修改默认密码,并把 qr_aes_key 改成自己的随机字符串。
演示数据(对外展示用)
内置一键生成脚本,造好 3 个班级、135 名学生、76 个作业和近 3000 条提交记录的“真实感”数据,方便演示宣传:
python make_demo.py # 首次生成
python make_demo.py --force # 删除旧演示班级后重新生成
演示账号:demo / 123456(王老师,拥有全部演示班级)
- 班级:初一(1)班 45 人 / 初二(3)班 42 人 / 高一(2)班 48 人,各 5 门学科
- 每学科 4~6 个作业分布在最近 30 天,每学科最新一个为“进行中”,打开即可现场扫码演示
- 上交率 80%~95%,部分标记“已完成”,含扫码次数与时间;随机种子固定,多次生成结果一致
- 同时生成初一(1)班全部学科的二维码贴纸 PDF(
data/演示数据/ 目录),可直接打印展示
移动端适配
界面为移动优先设计(手机竖屏体验最佳):底部导航栏、表格自动变卡片、扫码面板吸顶、大按钮触控。电脑浏览器同样完整可用,登录页可直接手机访问。
配置
配置文件:data/config.json,首次运行自动生成。
| 配置项 |
说明 |
teachers |
老师账号列表(用户名/密码/姓名/是否管理员)。配置文件是账号的唯一来源,修改后重启生效。 |
qr_aes_key |
二维码 AES 加密密钥。建议改成自己的随机字符串,改后旧二维码作废需重新打印;其他客户端必须用同一密钥才能解密。 |
host / port |
监听地址与端口。 |
密钥只能由字母/数字/符号组成,长度不限。修改后重启服务并重新生成 PDF。
使用流程
- 登录 → 新建班级 → 进入班级添加学科 → 批量添加学生(姓名+学号)。
- 班级页选择学科(或全部学科)→「生成PDF」→ 打印 → 裁剪 → 粘贴到学生本子上。
- 班级页「发起作业」(选学科、填标题)→ 进入作业页 →「批量扫码」收作业。
- 收完在作业页点「结束作业」;去「统计报表」看未交名单和各项统计。
摄像头扫码说明
浏览器调用摄像头需要安全上下文:localhost 或 HTTPS。
- 部署在服务器上时,请在服务器端配置 HTTPS(Nginx/Caddy 反向代理、云平台负载均衡的证书均可),手机浏览器即可正常扫码。
- 服务器端未配 HTTPS 时,手机通过公网 IP/域名访问会被浏览器禁用摄像头(“电脑能扫、手机不能扫”就是这个原因)。
- 使用手机扫码时,浏览器会弹出摄像头权限请求,需点「允许」。
- 若某台手机浏览器仍无法调起摄像头(个别老旧浏览器/内置浏览器限制),可用作业页的「输入学号」兜底。
- Windows 防火墙若拦截,需放行 Python 的入站连接(按实际配置端口放行,默认
5098),才能让手机访问。
二维码格式(对接老师的客户端)
二维码内容为以下明文加密后的 Base64:
V1|班级名称|学科名称|学号
加密算法:
- AES-128-ECB + PKCS7 填充
- 密钥 =
SHA256(qr_aes_key 配置值) 的前 16 字节
- 输出标准 Base64(带填充)
以后其他客户端扫码后按同样算法解密,解析出班级、学科、学号即可定位作业与学生。
Python 参考实现:
import base64, hashlib
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
def _key(k):
return hashlib.sha256(k.encode()).digest()[:16]
def decrypt_qr(code: str, config_key: str) -> str:
raw = unpad(
AES.new(_key(config_key), AES.MODE_ECB).decrypt(
base64.b64decode(code)
),
16
)
return raw.decode('utf-8')
# -> "V1|初一(1)班|数学|20250101"
def encrypt_qr(plain: str, config_key: str) -> str:
return base64.b64encode(
AES.new(_key(config_key), AES.MODE_ECB).encrypt(
pad(plain.encode('utf-8'), 16)
)
).decode()
数据与备份
全部数据在 data/homework.db(单文件 SQLite),备份它即可。
删除班级/学科/学生会连同其下作业记录一并删除,操作有确认弹窗。
常见问题
-
扫二维码提示“无法解密”
qr_aes_key 被改过,或二维码是旧密钥生成的。重新生成 PDF 即可。
-
扫码提示“没有进行中的作业”
该班级学科下还没发起作业,或作业已结束。先去班级页发起作业。
-
重复扫码
同一学生扫多次会提示“重复扫码”,状态和计数不受影响(仅记录扫码次数)。
支持项目 / 收藏本帖
更新以 GitHub 仓库为准,感谢支持。