文档部署到 /ny-exam-platform 子路径 + 移除快照/趋势/异常 + 打印与 UI 全面完善

文档站(#88)
- base 默认改为 /ny-exam-platform/,可用 DOCS_BASE=/ 覆盖本地预览
- 新增 DOCS_OUT 环境变量,避免构建时清空输出目录失败导致产物半截
- 新增 tools/docs-preview.js:按子路径重写路由的本地预览服务
- 删除 docs/guide/snapshot.md,同步清理全部相关文档

移除存快照 / 趋势 / 异常(#89)
- 后端:删除 api.php 的 snapshot_save/list/delete/trend 四个 action 与
  $WRITE_ACTIONS 中的同名条目;删除 lib/Snapshot.php 与自动加载注册;
  DataService 移除 detectAnomalies() 及其调用
- 前端:移除三个按钮与三个弹窗、相关 JS 处理与 state 字段
- 测试:移除对应用例,补充 5 条名单导入列识别断言(17+9+18+32+29+11 全过)

打印完善(#90)
- 改用隐藏 iframe 输出,规避弹窗拦截;@page A4 支持纵向/横向
- 表头每页重复、行内不跨页断开、全表连续名次、可选「是否合格」列
- 分组小计(人数/平均/最高/最低/合格人数与合格率)、可附缺考名单另起一页
- 末尾签字栏;缺考名单打印改为同一套输出

UI / 交互 / Bug 修复(#91)
- dashboard.php:补「← 主系统 / 退出」入口(此前全屏后无法离开);
  修复成员下钻 onclick 里 JSON.stringify 双引号提前闭合属性导致点击报错,
  改为 data-sid 事件委托;补 Esc 关弹窗;后台标签页暂停轮询、切回自动补拉;
  刷新中断原因写入 title;数值字段统一兜底,避免 NaN / undefined%
- draw.php / draw.js:结果表新增「登陆账号」列(导出前可核对,缺失显示 学号 ⚠);
  弹窗只关最上层且支持 Esc;「全部」改为跟随候选池,手工改人数即解除;
  候选池不足时给出明确提示;自定义比例框隐藏时清空,避免旧权重被误读
- app.js / dashboard.php:成绩着色改为按「占本卷满分的百分比」判断,
  修复满分不是 100 时整列误标红
- style.css:数值列右对齐;新增 subbar、draw-stage-sub;
  看板顶栏窄屏下拉与按钮换行,消除横向滚动
This commit is contained in:
2026-09-11 16:23:08 +08:00
parent f271066266
commit 25a2e8a42c
30 changed files with 700 additions and 883 deletions
+10 -1
View File
@@ -13,6 +13,14 @@
| 自动刷新开关 + 间隔 | 与主页面一致的 5 / 10 / 15 / 30 / 60 / 120 秒 |
| 刷新 | 立即拉取一次(跳过缓存) |
| ⛶ 全屏 | 进入 / 退出全屏,布局自动铺满 |
| ← 主系统 | 返回主页面(成绩明细 / 名单 / 抽取);全屏状态下也可直接返回 |
| 退出 | 退出登录 |
::: tip 后台标签页会自动暂停
切换到其他标签页后看板会**停止轮询**,切回来时立即补拉一次数据并重新开始计时——
投屏时长开也不会在无人观看时反复请求卷王。自动刷新失败时,「最后更新」会显示
**刷新中断(仍显示上次数据)**,鼠标悬停可看到具体原因。
:::
## 汇总卡片
@@ -25,7 +33,8 @@
看板主体按**班级**分块,每块内再按**组别**对比,指标与统计口径完全相同:
总人数、已提交、缺考、提交率、平均分、合格率、最高分、最低分、平均用时。
点击班级内任意成员可查看其**每一次提交**(时间、成绩、时长),最高分有标记。
点击考过多次的成员(带「刷 N 次」标签)可查看其**每一次提交**(时间、成绩、时长),最佳成绩有标记。
按 `Esc` 或点击弹窗外部可关闭。
> 未分班的人归入「(未分班)」,未分组的人归入「(未分组)」,不会丢失。
+11 -3
View File
@@ -44,7 +44,15 @@
顶部卡片:`候选人数 / 本次抽取 / 累计已抽取 / 已排除 / 抽取来源`。
结果表格:`序号 / 学号 / 姓名 / 班级 / 组别 / 操作`。
结果表格:`序号 / 学号 / 姓名 / 班级 / 组别 / 登陆账号 / 操作`。
「登陆账号」列让你在导出前就能核对:显示为 `学号 ⚠` 表示名单里没填这一列,
导出时会自动回退用学号——**这会导致学生登不进考试**,请先回主系统「名单管理」补全。
::: tip 「全部」按钮会跟随候选池
点 **全部** 后抽取人数进入跟随模式:切换班级 / 组别 / 来源时人数自动更新为当前
候选池大小。手工改动人数输入框即解除该模式。
:::
| 按钮 | 说明 |
| --- | --- |
@@ -57,8 +65,8 @@
## 登陆账号说明
名单中的**登陆账号**列只在这里用于导出白名单,主系统界面任何位置都不展示。
若名单里没有这一列,导出的白名单该字段为空。
名单中的**登陆账号**列在这里既用于导出白名单,也会直接显示在结果表格中(便于导出前核对)。
若名单里没有这一列,抽取结果里会用 `学号 ⚠` 标出,导出时回退用学号。
::: warning 模板文件名
卷王模板中该列表头为「登陆账号」(不是"登录账号"),导出时已按此命名。
+24 -6
View File
@@ -2,7 +2,8 @@
## 导出成绩明细
工具栏 **导出成绩**,生成 `.xlsx`(零依赖,仓库内自行实现 XLSX 写入,不需要 `zip` 扩展也能用)。
工具栏下方「导出」条里的 **导出成绩**,生成 `.xlsx`(零依赖,仓库内自行实现 XLSX 写入,不需要 `zip` 扩展也能用)。
导出控件单独成行,与筛选、刷新分开,不会挤在一起。
### 三种可选模式
@@ -41,13 +42,30 @@
## 打印成绩明细
成绩明细面板右上角 **打印**:
成绩明细面板右上角 **打印**,弹窗里可设置:
- 默认按**成绩降序**;
- 可选「按班级 / 组别分组对比」,每组段首给出小计;
- 走浏览器打印通道,可直接另存为 PDF。
| 选项 | 说明 |
| --- | --- |
| 打印标题 | 默认「试卷名 + 成绩明细」,可改成学校/考试正式名称 |
| 排序方式 | 成绩降序(默认)/ 升序 / 学号 / 提交时间 |
| 分组对比 | 按班级或组别分段,段首给出小计(人数/平均/最高/最低/合格人数与合格率) |
| 纸张方向 | A4 纵向(列少清晰)或横向(列多不折行) |
| 显示名次 | 全表连续编号,不分组也不会因为分段重新从 1 开始 |
| 显示「是否合格」列 | 低于合格线的成绩与「不合格」标红,一眼定位 |
| 显示考试次数 | 便于发现反复重考的人 |
| 附缺考名单 | 成绩表后**另起一页**附缺考名单,带空白备注列供手写 |
缺考名单面板右上角 **打印** 同理。
其它细节:
- 表头在**每一页自动重复**,行不会被切断到两页;
- 页眉含范围(班级/组别)、打印时间、人数、平均分、最高/最低、合格人数与合格线;
- 页脚含**教师 / 教研组长签字栏与日期**,可直接签字归档;
- 打印走隐藏 iframe 调起,**不会被浏览器的弹窗拦截挡掉**,也不会多开标签页。
## 打印缺考名单
缺考名单面板右上角 **打印**:按班级分组、班内按学号排序,同样带页眉与签字栏,
备注列留空供手写说明(请假、缓考等)。
## 直接调用导出接口
+1 -1
View File
@@ -86,7 +86,7 @@
**Q:可以把平台搬到另一台服务器吗?**
可以。整个目录复制过去,并把 `data/` 一起带上(里面有配置、名单、快照),确保 `data/` 可写。
可以。整个目录复制过去,并把 `data/` 一起带上(里面有配置、名单、每卷配置),确保 `data/` 可写。
## 安全
+1 -2
View File
@@ -97,11 +97,10 @@ Apache 下 `data/` 默认即被保护。仍需确认:
| 路径 | 需要 | 说明 |
| --- | --- | --- |
| `data/` | 可写 | 配置、名单、令牌、快照的根目录 |
| `data/` | 可写 | 配置、名单、令牌的根目录 |
| `data/ny.db` | 可写 | SQLite 主库(启用 `pdo_sqlite` 时) |
| `data/uploads/` | 可写 | 导入名单时的临时落盘,解析后立即删除 |
| `data/cache/` | 可写 | 卷王令牌缓存、结果缓存 |
| `data/snapshots/` | 可写 | 成绩快照 |
```bash
chown -R www:www data
+3 -5
View File
@@ -26,12 +26,10 @@ NY 问卷考试系统数据平台是一个**零第三方运行依赖**的 PHP 8
| 试卷切换 | 下拉选择卷王中的问卷 / 考试,自动拉取该卷全部答卷 |
| 姓名关联 | 自动识别答卷中的「姓名」题,也可手动指定字段;未匹配答卷单独面板 + 一键补入名单 |
| 统计卡片 | 名单总人数、已提交、缺考、平均分、最高分、最低分、合格率、平均用时;选择班级后全部联动 |
| 成绩明细 | 虚拟滚动(无分页)、点击表头排序、搜索、考试次数、新提交绿色高亮(30 秒自动清除) |
| 缺考名单 | 名单中有但未提交的人,支持复制学号 / 姓名、打印 |
| 成绩明细 | 虚拟滚动(无分页)、点击表头排序、搜索(提示同步显示命中数)、考试次数、新提交绿色高亮(30 秒自动清除) |
| 缺考名单 | 名单中有但未提交的人,支持复制学号 / 姓名、打印(按班级分组) |
| 试卷设置 | 为当前选中的试卷单独设置满分 / 合格率 / 免考名单,试卷间互相隔离 |
| 快照 / 趋势 | 保存带标签的时间点快照,横向对比每名学生成绩变化 |
| 异常检测 | 短时长高分、高频重考、雷同成绩三类线索 |
| 导出 / 打印 | 成绩明细、缺考名单 `.xlsx`;成绩明细按成绩降序打印,可选分组对比 |
| 导出 / 打印 | 成绩明细、缺考名单 `.xlsx`;成绩明细按成绩降序打印,支持分组小计、合格标记、附缺考名单、签字栏 |
### 数据看板 `dashboard.php`
+15 -1
View File
@@ -9,6 +9,7 @@
| 名单总人数 | 名单条目数;被当前试卷设为**免考**的人不计入 |
| 已提交 | 匹配到名单、且提交了答卷的人数(去重后的代表成绩行数) |
| 缺考 | `max(0, 名单总人数 − 已提交)` |
| 提交率 | `已提交 ÷ 名单总人数 × 100%`——考试进行中最该盯的指标 |
| 提交率 | `已提交 ÷ 名单总人数 × 100%` |
| 平均分 | 所有**有成绩**的答卷成绩平均值;无成绩者不计入分母 |
| 最高分 / 最低分 | 同上,取自所有有成绩的答卷 |
@@ -40,7 +41,20 @@
| 提交时间 | **最近一次**提交时间(重考低分也会让这行按最新时间排序到最上面) |
| 考试时长 | 最近一次答卷的时长;后台手动录入等没有起止时间的答卷为 `-` |
点击任意一行可查看该学生的**每一次提交**(时间、成绩、时长),最高分有标记。
点击任意一行可查看该学生的**每一次提交**(时间、成绩、时长),最佳成绩有标记。
### 成绩颜色
成绩按**占本卷满分的百分比**着色,而不是写死的 90 / 60 分:
| 颜色 | 条件 |
| --- | --- |
| 绿色 | ≥ 满分的 90% |
| 橙色 | ≥ 合格率线(默认满分的 60%,可在[每卷配置](./project-config.md)里改) |
| 红色 | 低于合格率线 |
这样把满分改成 50 分或 20 分制时,不会因为绝对分数偏低而整列误标红。
数据看板的成员榜使用同一套规则。
## 排序与搜索
+2 -2
View File
@@ -6,8 +6,8 @@
| 配置项 | 默认值 | 说明 |
| --- | --- | --- |
| 卷王系统地址 | `https://exam.nxxy335.top` | 结尾不带 `/` |
| 接口前缀 | `/api` | 社区版 `/api`;企业版可能用 `/admin-api` |
| 卷王系统地址 | `https://exam.nxxy335.top` | 结尾不带 `/`,可直接在设置里修改 |
| 接口前缀 | `/api` | 社区版 `/api`;企业版可能用 `/admin-api`;可直接在设置里修改 |
| 登录账号 | `admin` | 卷王后台管理员账号 |
| 登录密码 | `123456` | 不回显;留空表示不修改 |
| 校验 HTTPS 证书 | 勾选 | 自签名证书取消勾选 |
-72
View File
@@ -1,72 +0,0 @@
# 快照、趋势与异常检测
这一组功能用于**跨时间**看成绩,而不是只看当前这一刻。
## 快照
工具栏 **存快照** 打开快照面板,填写标签(留空自动用「快照 MM-DD HH:II」)后保存。
一份快照包含:
- 保存时间与标签;
- 试卷 ID 与名称;
- 当时的整体统计(总人数、已提交、平均分、合格率……);
- 每名学生的 `学号 / 姓名 / 班级 / 组别 / 成绩 / 最高分 / 考试次数 / 最近提交时间`(按学号排序)。
存储位置:`data/snapshots/<projectId>/<unix秒>_<md5(标签)>.json`。
快照**按试卷分目录**,所以不同试卷的快照互不干扰。
| 操作 | 位置 |
| --- | --- |
| 保存当前快照 | 快照弹窗 → 保存当前快照 |
| 刷新列表 | 快照弹窗 → 刷新列表 |
| 删除某份 | 列表每行的删除按钮 |
## 趋势
**趋势** 面板把同一试卷的多份快照横向铺开,按学号对齐,可以直接看出每名学生
在几个时间点上的分数变化(上升 / 下降 / 缺考)。
典型用法:
1. 月考卷 A 考完 → 存快照「10月月考」;
2. 期中卷 B 考完 → 存快照「期中」;
3. 打开趋势,逐人对比两次成绩。
## 异常检测
工具栏 **异常** 打开异常线索面板。它**不是判定作弊**,只是把值得人工复核的对象挑出来,
避免在上千行数据里肉眼找。
### 短时长高分
命中条件:
```
有时长记录
且 时长 < max(60秒, 平均时长 × 40%)
且 成绩 ≥ 满分提示值 × 85%
```
> 「满分提示值」取当前数据中的最高分(`max_score`),至少为 1。
### 高频重考
命中条件:`考试次数 ≥ max(4, ceil(平均考试次数 + 3))`
即:至少 4 次才算高频,且要明显高于整体平均水平。
### 雷同成绩
同一分数出现 **≥ 3 人** 时列为疑似,按人数降序排列并列出成员。
::: warning 请人工复核
异常检测基于统计特征,误报很正常(例如题目全是选择题时同分很常见)。
请把它当作"值得看一眼"的线索,不要直接作为处理依据。
:::
## 相关
- [成绩明细与统计口径](./scores.md)
- [导出与打印](./export-print.md)