Files
nxxy335 a3be81b261 fix(security): 修复上传名单文件可被 URL 直连访问(nginx 下可 getshell)
严重漏洞:roster_import 使用 $_FILES 的原始扩展名拼 roster_YYYYMMDD_HHMMSS.<ext>
落在 Web 根目录内的 data/uploads/,既无扩展名白名单(可上传 .php),文件名又
可按秒枚举;而 bootstrap 只写了 data/.htaccess,nginx 不读 .htaccess,
生产环境(nginx + PHP-FPM)下可直接远程代码执行。

修复(api.php roster_import 四层防护):
- 扩展名白名单:仅 xlsx / xlsm / csv / txt
- 随机文件名:bin2hex(random_bytes(16)),杜绝枚举
- 解析完成后 @unlink 立即删除,Web 目录下不留存任何上传文件
- 20MB 大小限制 + UPLOAD_ERR 检查

加固(bootstrap.php):data 及 cache/uploads/snapshots 每个目录都写
.htaccess(Deny from all)+ index.html 占位;README 与文档补充 nginx
location ^~ /data/ { deny all; return 404; } 规则。

测试:新增 e2e tools/test-upload-guard.js(11 断言,覆盖 .php/.phtml 被拒、
无残留、合法 csv 导入成功且即删、无可枚举文件名),并入 tests/run-all.sh。
全套 90 项通过。

docs: 新增 VitePress 文档站(18 页)
- 使用指南 12 页:简介/部署/快速上手/系统设置/名单管理/统计口径/试卷设置/
  快照趋势异常/导出打印/数据看板/随机抽取/常见问题
- 安全 2 页:安全总览(含本次漏洞复盘)与部署加固清单(P0-P2)
- 开发 4 页:架构与目录/接口一览/SQLite 存储/测试
- 配图迁移至 docs/public/images/;.gitignore 忽略文档构建产物
2026-09-10 22:42:13 +08:00

68 lines
2.3 KiB
Markdown
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.
# 试卷设置(满分 / 合格率 / 免考)
不同试卷满分往往不同(100 分制、150 分制、50 道题每题 2 分……),合格率要求也可能不同。
所以**满分的每卷配置放在主页面「试卷设置」里,而不是系统设置**——设置里只保留全局默认值。
## 打开方式
主页面工具栏 → **试卷设置**(按钮为高亮主色)。配置**只对当前选中的试卷生效**。
## 优先级
```
本卷配置 > 全局默认(系统设置)
```
未设置某项时显示"跟随全局(X)",保存后卡片标题与统计口径立即更新。
## 满分
- 用于合格率阈值计算和卡片展示;
- 留空或填 `0` = **清除本卷配置**,回落全局默认;
- 全局默认满分在 **设置 → 全局默认满分** 中修改。
## 合格率
- 百分比,含义是「成绩 ≥ 满分 × X%」记合格。例如满分 150、合格率 60 → 90 分及格;
- 留空 = 跟随全局;录入范围会被夹到 `1 ~ 100`;
- 保存后统计卡片标题会变成 `合格率 (≥60%满分)`,与实际口径一致。
::: tip 为什么不再写死 60%
早期版本把「≥60% 满分」硬编码在代码里,一旦满分不是 100 就会产生误导。
现在阈值可配、可每卷覆盖,且界面上直接显示当前阈值。
:::
## 免考名单
某些人因故不参加本卷考试(缓考、免修、已单独补考等),如果直接把他们从名单里删除,
其它试卷的统计也会受影响。免考名单解决的就是这个:
- 填写**学号**列表,支持逗号、中文逗号、空格、换行分隔;
- 生效范围:仅当前试卷;
- 效果:这些人**不计入名单总人数,也不计入缺考**,彻底从本卷的分母中移除;
- 若他们实际上也交了卷,答卷仍会出现在成绩明细中。
示例输入:
```
2024012001, 2024012002
2024012015
```
## 清除本卷设置
弹窗左下角 **清除本卷设置** 会删除该试卷的全部独立配置(满分、合格率、免考),
之后完全跟随全局。
## 存储
| 环境 | 位置 |
| --- | --- |
| 启用 `pdo_sqlite` | `data/ny.db` 表 `ny_project_config`(主键 `project_id`) |
| 未启用 | `data/project_config.json` |
## 相关
- [系统设置](./settings.md)(全局默认值)
- [成绩明细与统计口径](./scores.md)