feat(export/dashboard): 导出增强与大屏公开化
导出-每次考试/多考试对比: - 合格次数阈值等标记项抽为常显区块,三类成绩表共用 - 附缺考名单扩展到多考试导出(取所选考试全都没交的人) - 块表每场固定2列(成绩+合并空位),修复漏推空串导致的整行左移/串列 - 列宽按实际内容估算,合并区空位只给最小宽度 - 合格次数始终显示实际次数(含0),仅 ≥ 阈值标绿底 - 打印标题改为「成绩明细」,缺考名单分页单独成页 - 打印样式加 print-color-adjust:exact,绿底/红字可正常印出 数据大屏: - ?class= 班级大屏免登录公开访问,接口侧放行并按班级裁剪后回传 - 单班大屏移除退出按钮,仅首页保留 - 修复红绿判定真bug:membersTable 误用 window.DASH(DASH为let声明取不到) 改为 scoreGrade() 直接读自由变量,按后台合格率正确判红/黄/绿 测试/样例/文档同步更新,全量回归通过。
This commit is contained in:
+40
-3
@@ -39,7 +39,7 @@
|
||||
| --- | --- | --- | --- |
|
||||
| `projects` | GET | — | 卷王项目(问卷 / 考试)列表 |
|
||||
| `data` | GET | `projectId`、`nameQid`、`force` | 主系统数据:统计、成绩行、名单、缺考、未匹配 |
|
||||
| `dashboard` | GET | `projectId`、`nameQid`、`force` | 按班级 / 组别聚合的看板数据 |
|
||||
| `dashboard` | GET | `projectId`、`nameQid`、`force`、`class` | 按班级 / 组别聚合的看板数据。`class` 非空且未登录时,服务端只回这一个班(并标记 `public`) |
|
||||
|
||||
`data` 响应关键字段:
|
||||
|
||||
@@ -75,12 +75,49 @@ _cache { cached, at }
|
||||
|
||||
| Action | 方法 | 参数 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `export` | GET | `projectId`、`cls`、`grp`、`mode=latest`、`split=cls`、`sort`、`cols` | 成绩明细 `.xlsx` |
|
||||
| `export_absent` | GET | 同上 | 缺考名单 `.xlsx` |
|
||||
| `export` | GET | `projectId`、`nameQid`、`cls`、`grp`、`mode=latest\|all`、`scoreMode=latest\|best`、`split=cls`、`sort`、`cols`、`skipTemp=1`、`noAbsent=1` | 成绩明细 `.xlsx`(`all` 时每人每次考试一行) |
|
||||
| `export_absent` | GET | `projectId`、`nameQid`、`cls`、`grp` | 缺考名单 `.xlsx` |
|
||||
| `export_multi` | GET | `projectIds`(逗号分隔)、`nameQid`、`mode=block\|summary\|both`、`wide=1`、`passTimes`、`markBest=0`、`passRow=0`、`scoreMode=latest\|highest`、`cls` / `grp`(可多值)、`withCls` / `withGrp`、`includeTemp`、`format=json` | 「每次考试」块表 / 宽表 / 成绩对比 `.xlsx`(`format=json` 时返回装配结果供前端打印) |
|
||||
| `draw_export` | GET | `type=import\|list` | 白名单导入模板 / 白名单列表 |
|
||||
|
||||
`sort` 取值:`time` / `sid` / `score_desc` / `score_asc`。
|
||||
|
||||
### 导出新参数
|
||||
|
||||
| 参数 | 适用接口 | 取值 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `mode=all` | `export` | 缺省 | 每次考试一行(同一学号考 N 次就有 N 行);`mode=latest` 为每人一行最新成绩 |
|
||||
| `scoreMode=best` | `export` | 缺省 | 每人一行的代表成绩改取**最高成绩**(默认 `latest` = 最近一次真实提交);`mode=all` 不生效 |
|
||||
| `noAbsent=1` | `export`、`export_multi` | 缺省 | 不附缺考名单工作表(`export_multi` 口径:所选考试全都没交的人) |
|
||||
| `skipTemp=1` | `export` | 缺省 | `mode=all` 时排除暂存草稿;`includeTemp=1` 可强制保留 |
|
||||
| `mode=block` | `export_multi` | **默认** | 两行表头的「每次考试」块表:一列「第几次」被所有考试共用,每场考试占 2 列(考试名横跨 2 列 + 第二行「成绩」小标题),学生块末尾一行「合格次数」,学号·姓名纵向合并,没考的考试合并成「未考」(旧值 `merged` / `attempts` 等价) |
|
||||
| `wide=1` | `export_multi` | — | 只传 1 个 `projectId` 时改用宽表:每人一行、第几次直接做列名(`学号 / 姓名 / 第1次…第N次 / [合格次数]`),由 `ny_assemble_attempt_wide_sheet()` 生成 |
|
||||
| `passTimes` | `export_multi` | 1 | 「合格次数」达标阈值:该场达到合格线的次数 ≥ 此值才标绿(默认 1) |
|
||||
| `markBest=0` | `export_multi` | 开 | `=0` 取消「最高分标红」 |
|
||||
| `passRow=0` | `export_multi` | 开 | `=0` 不输出「合格次数」行(也就没有绿底) |
|
||||
| `mode=summary` | `export_multi` | — | 成绩对比:一行一个学生、一列一场考试(旧值 `matrix` 等价) |
|
||||
| `mode=both` | `export_multi` | — | 第一张块表 + 第二张成绩对比表 |
|
||||
| `format=json` | `export_multi` | — | 不下载文件,`ny_ok` 返回 `sheets`(`rows` / `merges` / `widths` / `header_rows` / `cell_styles`)+ `meta`(考试名、场次、班级 / 组别、列开关、`pass_line` / `pass_times` / `mark_best` / `pass_row` / `wide`),供「多考试打印」渲染 |
|
||||
| `cls` / `grp` | `export_multi` | 新增 | 支持多选(逗号分隔),空 = 全部;与单考试 `export` 的筛选口径一致 |
|
||||
| `withCls` / `withGrp` | `export_multi` | 新增 | 强制出 / 不出班级、组别列;缺省由 `ny_multi_col_flags()` 判定:选 ≥2 个班级(组别)才出,只选 1 个班级且未选组别两列都不出 |
|
||||
| `includeTemp=1` | `export_multi` | 缺省 | 不传 = 块表默认跳过暂存草稿(保留时标注 `第N次(草稿)`) |
|
||||
|
||||
块表由 `ny_assemble_block_sheet()` 生成,返回 `rows`(两行表头 + 学生块)/ `merges` / `widths` / `header_rows=2`
|
||||
/`cell_styles`;宽表由 `ny_assemble_attempt_wide_sheet()` 生成,参数同上。
|
||||
合格线按**每场各自**的 `ny_resolve_score_cfg($pid, $c)` 解析(本卷满分 × 合格率),不是全场统一一条线。
|
||||
|
||||
`cell_styles` 是 `行,列 → red | green`(行与列均 **1-based**),只有两类标记:
|
||||
|
||||
- `red` —— 该场该生成绩 = 该场最高分(同分只标最早达成的那次);
|
||||
- `green` —— 该场该生成绩达到合格线的次数 ≥ `passTimes`(未达标不标记)。
|
||||
|
||||
`XlsxWriter::renderMulti()` 支持 `merges`(1-based 闭区间 `[r1,c1,r2,c2]`)、`header_rows`(多行表头同样式)
|
||||
与 `cell_styles`(单元格级红字 / 绿底);被合并的非首格写成「空值 + 同样式」以保证合并区域四周边框完整,
|
||||
并跟随左上角首格的标记,避免绿底只覆盖半个格子。
|
||||
前端 `sheetToHtml()` 把同一份 `merges` 换算成 `colspan` / `rowspan`、把 `cell_styles` 换算成红字 / 绿底,
|
||||
所以**打印与导出的 Excel 用同一套判定**。
|
||||
列显示规则 `ny_multi_col_flags()` 与排序比较函数同样放在 `lib/multi_export.php`(纯函数,可单测)。
|
||||
|
||||
## 前端调用约定
|
||||
|
||||
```js
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
```
|
||||
ny-exam-platform/
|
||||
├─ index.php 主系统页面(服务端渲染骨架 + 前端挂载)
|
||||
├─ dashboard.php 数据看板页面
|
||||
├─ dashboard.php 数据大屏:首页(班级入口)+ ?class= 单班大屏(锁后退)
|
||||
├─ draw.php 随机抽取页面
|
||||
├─ login.php / logout.php 登录与登出
|
||||
├─ api.php 所有后端接口(单一入口,?action=xxx)
|
||||
|
||||
+50
-4
@@ -14,9 +14,45 @@ bash tests/run-all.sh
|
||||
| --- | --- | --- |
|
||||
| `tests/test-aggregate.php` | PHP | 聚合、去重、考试次数、排序 |
|
||||
| `tests/test-new-features.php` | PHP | 再次提交置顶排序、XLSX 多表、名单导入列识别 |
|
||||
| `tools/test-xlsxwriter.php` | PHP | XLSX 写入与 ZIP 打包 |
|
||||
| `tests/test-config-persist.php` | PHP | 配置双写兜底(DB / `config.json`) |
|
||||
| `tools/test-xlsxwriter.php` | PHP | XLSX 写入与 ZIP 打包、合并单元格、单元格级红字 / 绿底 |
|
||||
| `tests/test-multi-export.php` | PHP | 多考试块表与单场宽表的装配(合并区间、合格线、标红标绿、班级 / 组别列) |
|
||||
| `tools/test-config-save.js` | Node e2e | 配置保存、连接变化检测、每卷配置隔离、CSRF |
|
||||
| `tools/test-upload-guard.js` | Node e2e | 导入文件后缀白名单 |
|
||||
| `tools/test-whitelist.js` | Node e2e | 白名单导入 / 名单识别 |
|
||||
| `tools/test-login-loop.js` | Node e2e | 未配置账号 → 登录 → 已登录状态回流 |
|
||||
| `tools/test-dashboard-nav.js` | Node e2e | 数据大屏两种形态:`dash-home` / `dash-class` 骨架、顶栏控件收敛、后退锁定、班级卡片渲染 |
|
||||
| `tools/test-draw-alloc.js` | Node e2e | 随机抽取名额分配(加权 / 自定义 / 守恒 fuzz) |
|
||||
| `tools/test-block-print.js` | Node(不需要服务) | 从 `assets/app.js` 抽取 `sheetToHtml` 校验合并区间换算与红 / 绿标记 |
|
||||
|
||||
> `tools/test-block-print.js`、`tools/make-samples.js`、`tools/test-dashboard-nav.js`、`tools/make-dash-sample.js`
|
||||
> 都会**直接从生产源码里抽取函数在真数据上执行**,而不是另抄一份渲染逻辑——改了这些函数,这几处会立刻暴露漂移。
|
||||
|
||||
::: warning 端口占用会让 e2e「假通过 / 假失败」
|
||||
每个 e2e 段用固定端口(`test-config-save.js` 18081、`test-whitelist.js` 18082、`test-upload-guard.js` 18083 等)。
|
||||
若上一次跑测试时中断,PHP 子进程可能变成**孤儿服务**继续占着端口:新一次运行时它的 `waitPort` 会照常通过
|
||||
(打到的是旧服务),于是登录直接失败、报错信息指向错误的连接地址。遇到"服务已就绪但登录失败",先查端口:
|
||||
|
||||
```bash
|
||||
netstat -ano | grep LISTENING | grep -E ":180[0-9][0-9]|:199[0-9][0-9]"
|
||||
taskkill //PID <pid> //F
|
||||
```
|
||||
:::
|
||||
|
||||
## 生成导出版式样例
|
||||
|
||||
想直观看新版式(以及验证打印与导出一致),可生成可打开的样例:
|
||||
|
||||
```bash
|
||||
php tools/make-samples.php # 出两版 xlsx + sheet-data.json
|
||||
node tools/make-samples.js # 用生产 sheetToHtml 渲染打印预览 HTML
|
||||
|
||||
node tools/make-dash-sample.js # 渲染数据大屏首页预览(含班级入口卡片)
|
||||
```
|
||||
|
||||
产物在 `docs/samples/`:打印预览 `preview-multi-block.html` / `preview-single-wide.html`
|
||||
(+ 对应 `.xlsx`),大屏首页预览 `dash-home-preview.html`。两者都自起 mock 服务与临时数据目录,
|
||||
不会读写项目 `data/`。
|
||||
|
||||
可通过环境变量覆盖运行时路径:
|
||||
|
||||
@@ -85,9 +121,19 @@ git status data/ # data/ 已被 gitignore,需手工核对
|
||||
- [ ] 点某一行 → 能看到该学生的每次提交
|
||||
- [ ] 导入含 `.php` 后缀的文件 → 被拒绝
|
||||
- [ ] 导入正常 `.xlsx` → 成功,且 `data/uploads/` 为空
|
||||
- [ ] 导出成绩 / 导出缺考 → 能打开,学号不是科学计数法
|
||||
- [ ] 打印预览 → 默认成绩降序
|
||||
- [ ] 数据看板全屏进入 / 退出都正常
|
||||
- [ ] 工具栏「导出」只一个按钮 → 弹窗里四种内容都能出表,学号不是科学计数法
|
||||
- [ ] 成绩明细「每人成绩」切 最高 / 最新 → 成绩列跟着变,文件名带 `_最高成绩` / `_最新成绩`
|
||||
- [ ] 每次考试导出 → 最高分红字、合格次数达标绿底、未达标留白、整场未考合并成「未考」;每场考试占 2 列,成绩不串列
|
||||
- [ ] 多考试打印 → 版式与导出的 Excel 一致,「合格次数」标签没被合并吞掉
|
||||
- [ ] 打印预览 → 默认成绩降序,没有教师签字栏、没有站点域名页脚;**绿底 / 红字真的印出来了**
|
||||
(打印样式带 `print-color-adjust: exact`,不需要在对话框里勾「背景图形」)
|
||||
- [ ] 导出弹窗「附加内容 · 附缺考名单」→ 每次考试 / 多考试对比也出「缺考名单」工作表
|
||||
- [ ] 在每卷配置里改满分成数 / 合格率 → 数据大屏成员榜的红绿跟着变
|
||||
- [ ] 数据大屏首页 → 选试卷后列出班级卡片,点击进入单班大屏
|
||||
- [ ] 单班大屏 → 顶栏只有试卷 / 自动刷新 / 全屏,没有班级选择与退出;按浏览器后退键**退不回去**
|
||||
- [ ] 复制单班大屏链接在**无痕窗口**打开 → 直接看到该班数据(免登录),顶栏有「公开 · 无需登录」角标;
|
||||
看不到其它班级的成绩;大屏首页仍要求登录
|
||||
- [ ] 数据大屏全屏进入 / 退出都正常
|
||||
- [ ] 随机抽取 → 名额守恒
|
||||
|
||||
## 相关
|
||||
|
||||
+65
-15
@@ -1,20 +1,43 @@
|
||||
# 数据看板
|
||||
# 数据大屏
|
||||
|
||||
数据看板(`dashboard.php`)是**面向投屏 / 大屏**的汇总视图,适合考试进行中实时监控提交进度。
|
||||
数据大屏(`dashboard.php`)是**面向投屏 / 大屏**的汇总视图,适合考试进行中实时监控提交进度。
|
||||
它有两种形态,由 URL 决定:
|
||||
|
||||
从主页面顶部导航 **📊 数据看板** 打开(新标签页)。
|
||||
| 形态 | 打开方式 | 长什么样 |
|
||||
| --- | --- | --- |
|
||||
| **首页(班级入口)** | 从主页面顶部导航 **📊 数据大屏** 打开,或直接访问 `dashboard.php` | 先选试卷 / 考试,下方以卡片列出该卷的所有班级;点卡片进入该班大屏 |
|
||||
| **单班大屏** | 点首页的班级卡片(等价于 `dashboard.php?pid=<问卷ID>&class=<班级名>`) | 只展示这一个班:5 张汇总卡 + 分组对比 / 成员榜 |
|
||||
|
||||
## 顶部操作
|
||||
首页是"入口",不是概览页——它不堆指标,只做一件事:让你**一次看到有哪些班,点进去看单个班**。
|
||||
|
||||
| 控件 | 说明 |
|
||||
| --- | --- |
|
||||
| 问卷 / 考试 | 选择要展示的试卷 |
|
||||
| 班级 | 选择后只展示该班级(需先选试卷) |
|
||||
| 自动刷新开关 + 间隔 | 与主页面一致的 5 / 10 / 15 / 30 / 60 / 120 秒 |
|
||||
| 刷新 | 立即拉取一次(跳过缓存) |
|
||||
| ⛶ 全屏 | 进入 / 退出全屏,布局自动铺满 |
|
||||
| ← 主系统 | 返回主页面(成绩明细 / 名单 / 抽取);全屏状态下也可直接返回 |
|
||||
| 退出 | 退出登录 |
|
||||
## 单班大屏是公开的,可以直接发链接
|
||||
|
||||
`dashboard.php?pid=<问卷ID>&class=<班级名>` **不需要登录**,任何人打开都能看到这一个班的数据
|
||||
(顶栏带「公开 · 无需登录」角标)。适合直接把链接发到班级群让孩子或家长自己看。
|
||||
|
||||
::: danger 公开的是"这一个班",不是全卷
|
||||
接口在**服务端**先按 `class` 把名单和答卷裁剪掉,再回传数据:公开链接拿不到全卷汇总,
|
||||
也拿不到其它班级的成绩。想看别的班,打开那个班自己的链接即可;不带 `class` 参数的
|
||||
大屏首页仍然要求登录。
|
||||
:::
|
||||
|
||||
::: warning 单班大屏没有回头路
|
||||
单班大屏**不显示**班级下拉、「← 主系统」和「退出」,页面内部也不存在回到首页的链接;
|
||||
浏览器**后退键同样被屏蔽**(页面加载后立刻 `pushState` 占位,任何 `popstate` 都再推回去)。
|
||||
想回主系统或换班,请在地址栏改 URL,或关闭标签页重新从首页进入。
|
||||
:::
|
||||
|
||||
## 顶部控件
|
||||
|
||||
| 控件 | 首页 | 单班大屏 |
|
||||
| --- | :-: | :-: |
|
||||
| 问卷 / 考试 | ✅ | ✅ 切换后若该班不在新卷名单里,会自动落到第一个班 |
|
||||
| 班级 | ✅ | ❌ 由 URL 固定,不提供切换 |
|
||||
| 自动刷新开关 + 间隔 | ✅ | ✅ |
|
||||
| 刷新 | ✅ | ✅ |
|
||||
| ⛶ 全屏 | ✅ | ✅ |
|
||||
| ← 主系统 | ✅ | ❌ 由 CSS 隐藏 |
|
||||
| 退出 | ✅ | ❌ 页面里不再渲染 |
|
||||
|
||||
::: tip 后台标签页会自动暂停
|
||||
切换到其他标签页后看板会**停止轮询**,切回来时立即补拉一次数据并重新开始计时——
|
||||
@@ -22,14 +45,41 @@
|
||||
**刷新中断(仍显示上次数据)**,鼠标悬停可看到具体原因。
|
||||
:::
|
||||
|
||||
## 汇总卡片
|
||||
## 首页:班级入口卡片
|
||||
|
||||
`总人数 / 已提交 / 缺考 / 提交率 / 平均分 / 合格率(≥X%满分)`
|
||||
每张卡片给出该班的速览,点整张卡片(或聚焦后按回车)进入该班大屏:
|
||||
|
||||
`总人数 / 已提交 / 缺考 / 平均分 / 合格率` + 一条提交率进度条;没交过卷的班也能一眼看到缺考数。
|
||||
|
||||
::: tip 首页也在自动刷新
|
||||
首页同样受自动刷新开关控制(默认 15 秒),卡片上的数字会跟着变,适合把整层楼/整个年级的
|
||||
提交进度投在一块屏上。
|
||||
:::
|
||||
|
||||
## 汇总卡片(单班大屏)
|
||||
|
||||
`总人数 / 已提交 / 缺考 / 平均分 / 合格率(≥X%满分)`
|
||||
|
||||
合格率卡片的阈值标签会随 [每卷配置](./project-config.md) 实时变化。
|
||||
|
||||
## 成绩的红绿怎么定的
|
||||
|
||||
成员榜(以及「刷 N 次」下钻弹窗)里的成绩颜色**完全按 [每卷配置](./project-config.md) 里
|
||||
管理员设的满分与合格率**判定,不是写死的:
|
||||
|
||||
| 占满分的比例 | 颜色 |
|
||||
| --- | --- |
|
||||
| ≥ 90%(合格线本身高过 90% 时则以合格线为准) | 🟢 绿 |
|
||||
| ≥ 合格率 × 满分(合格但未达优秀) | 🟡 黄 |
|
||||
| < 合格率 × 满分(不及格) | 🔴 红 |
|
||||
|
||||
例如把本卷满分改成 150、合格率改成 80%,那么 100 分只占 66.7% → 判红,130 分(86.7%)判黄,
|
||||
145 分(96.7%)判绿。鼠标悬停在分数上会显示「占满分 xx% 合格线 xx 分」。
|
||||
|
||||
## 班级 / 组别下钻
|
||||
|
||||
(即单班大屏的主体部分)
|
||||
|
||||
看板主体按**班级**分块,每块内再按**组别**对比,指标与统计口径完全相同:
|
||||
总人数、已提交、缺考、提交率、平均分、合格率、最高分、最低分、平均用时。
|
||||
|
||||
|
||||
+150
-44
@@ -1,88 +1,194 @@
|
||||
# 导出与打印
|
||||
|
||||
## 导出成绩明细
|
||||
工具栏下方只有一个 **导出** 按钮,所有导出与打印的选项都收在这个弹窗里,不再散落多个小按钮。
|
||||
选项在你打开弹窗前就配好了会**自动记住**(存本地),下次打开就是上次的设置。
|
||||
|
||||
工具栏下方「导出」条里的 **导出成绩**,生成 `.xlsx`(零依赖,仓库内自行实现 XLSX 写入,不需要 `zip` 扩展也能用)。
|
||||
导出控件单独成行,与筛选、刷新分开,不会挤在一起。
|
||||
> 生成的是 `.xlsx`:零依赖,仓库内自行实现 XLSX 写入,没有 `zip` 扩展也能用。
|
||||
|
||||
### 三种可选模式
|
||||
## 导出弹窗
|
||||
|
||||
| 分区 | 内容 |
|
||||
| --- | --- |
|
||||
| **导出内容** | 成绩明细 / 每次考试 / 缺考名单 / 多考试对比(四选一,选中后下方分区跟着变) |
|
||||
| **统计范围** | 班级 / 组别多选(不选 = 全部,按住 `Ctrl` / `⌘` 多选) |
|
||||
| **成绩口径与列** | 每人成绩(最新 / 最高)、排序、出表方式、按班级分工作表、附缺考名单 |
|
||||
| **多考试对比** | 表格形态、对比成绩、勾选要对比的考试 |
|
||||
| **附加内容** | 附缺考名单(成绩明细 / 每次考试 / 多考试对比 都出工作表) |
|
||||
| **标记与合格次数** | 合格次数阈值、最高分标红、输出「合格次数」行 |
|
||||
| **打印设置** | 纸张方向、打印标题 |
|
||||
|
||||
- 分区随「导出内容」显隐:选 **缺考名单** 时只保留范围与打印设置;
|
||||
选 **多考试对比** 时才出现考试勾选表;
|
||||
- **附加内容** 与 **标记与合格次数** 是三类成绩表共用的,不随导出内容消失;
|
||||
「按班级分工作表」只有成绩明细支持(置灰不可勾选);
|
||||
- 弹窗底部有**一句话汇总**(导什么、哪些考试、多大范围),导错了一眼能看出来;
|
||||
- 打印走隐藏 iframe 调起,**不会被浏览器弹窗拦截挡掉**,也不会多开标签页。
|
||||
|
||||
### 成绩明细:每人最新成绩 / 最高成绩
|
||||
|
||||
**默认按每人最新成绩显示**(最近一次真实提交),可选 **最高成绩**(该生在这些考试里的最高分)。
|
||||
|
||||
| 选项 | 效果 |
|
||||
| --- | --- |
|
||||
| 导出排序 | `按提交时间` / `按学号` / `按成绩降序` / `按成绩升序` |
|
||||
| 按最新成绩 | 每人**只导一行**:最近一次成绩 + 最高分 + 考试次数 |
|
||||
| 按班级分表 | 一个班级一个工作表(xlsx 多工作表) |
|
||||
| 每人成绩 | `最新成绩`(默认)/ `最高成绩` —— 每人一行时的代表成绩 |
|
||||
| 排序 | `按提交时间` / `按学号` / `按成绩降序` / `按成绩升序` |
|
||||
| 出表方式 | `每人一行(汇总)`(默认)/ `每次考试一行(明细)`:明细模式保留每位学生的历史提交 |
|
||||
| 附缺考名单 | 默认开;只导成绩时取消勾选(接口 `noAbsent=1`)。**每次考试 / 多考试对比 也支持**,口径为「名单里有、所选考试全都没交」 |
|
||||
| 按班级分工作表 | 一个班级一个工作表(xlsx 多工作表) |
|
||||
|
||||
### 列
|
||||
默认列:`学号 / 姓名 / 班级 / 组别 / 成绩 / 最高分 / 考试次数 / 最近提交时间 / 考试时长 / 考试时长(秒)`。
|
||||
|
||||
默认列(全部记录模式):
|
||||
## 「每次考试」块表(多场对比,主推格式)
|
||||
|
||||
`学号 / 姓名 / 班级 / 组别 / 成绩 / 考试次数 / 第几次 / 提交时间 / 考试时长 / 考试时长(秒)`
|
||||
勾选多场考试,选 **两行表头** 形态。**一列「第几次」被所有考试共用**,每场考试占 2 列,
|
||||
学生块末尾多一行 **合格次数**。
|
||||
|
||||
按最新成绩模式:
|
||||
| 学号 | 姓名 | 第几次 | 第一次月考·数学 | | 第一次月考·英语 | |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| | | | 成绩 | | 成绩 | |
|
||||
| (合并) | (合并) | 1 | 112 | 112 | 130 | |
|
||||
| (合并) | (合并) | 2 | 100 | | 129 | |
|
||||
| (合并) | (合并) | 3 | **136** | | **133** | |
|
||||
| (合并) | (合并) | **合格次数** | 3 | | 3 | |
|
||||
| 356002 | 李四 | 1 | (合并)**未考** | | 128 | |
|
||||
| (合并) | (合并) | **合格次数** | | | 1 | |
|
||||
|
||||
`学号 / 姓名 / 班级 / 组别 / 最新成绩 / 最高分 / 考试次数 / 最近提交时间 / 考试时长 / 考试时长(秒)`
|
||||
规则:
|
||||
|
||||
> 学号等长数字列统一按**文本格式**写入,不会被 Excel 转成科学计数法,也不会被当作公式执行。
|
||||
- **学生块高度** = 该生在所有勾选考试里最多的那次次数 + 1(末行是合格次数);
|
||||
- **学号 / 姓名**按学生块纵向合并;**第几次**只合并到最后一次考试行,末行留给「合格次数」标签;
|
||||
- **考试名称横跨 2 列**,第二行是 `成绩` 小标题;
|
||||
- **没考的考试**(整场没有该生记录)→ 该场 2 列 × 学生块高合并成一个 **`未考`** 格子;
|
||||
- **排序**:学生按学号升序(出现班级 / 组别列时按 班级 → 组别 → 学号);
|
||||
- **暂存草稿**:默认不导出、也不占「第几次」编号。
|
||||
|
||||
### 单场考试的宽表版式
|
||||
|
||||
只导出 **一场** 考试时,改用更清楚的宽表:每人一行,第几次直接做列名。
|
||||
|
||||
| 学号 | 姓名 | 第1次 | 第2次 | 第3次 | 合格次数 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 356001 | 张三 | 112 | 100 | **136** | 3 |
|
||||
| 356002 | 李四 | **128** | | | 1 |
|
||||
|
||||
导出与打印用的是同一套判定,所以单场和「多场块表」的标记完全一样。
|
||||
|
||||
## 红 / 绿标记
|
||||
|
||||
| 标记 | 条件 | 效果 |
|
||||
| --- | --- | --- |
|
||||
| **最高分标红** | 该场该生成绩 = 该场最高分 | 红字加粗(同分只标最早达成的那次) |
|
||||
| **合格次数标绿** | 该场该生达到合格线的次数 ≥ 阈值 | 绿底加粗 |
|
||||
| 合格次数未达标 | 未达阈值 | **仍显示实际次数**(含 0 次),只不标绿 |
|
||||
|
||||
- 合格线 = 该场**本卷满分 × 合格率**(每个试卷各自的配置,不是全场统一一条线);
|
||||
- 阈值在弹窗里可改(默认 1 次);关掉「最高分标红」或「合格次数行」就只出表不标记;
|
||||
- 整场没考的不参与合格次数判定,直接是 `未考`;
|
||||
- 学号等长数字列统一按**文本格式**写入,不会被 Excel 转成科学计数法,也不会被当公式执行;
|
||||
- 打印与导出的 Excel 用同一份服务端装配结果(红字 / 绿底也来自同一份 `cell_styles`),
|
||||
不存在「导出一个样、打印另一个样」。
|
||||
|
||||
## 班级 / 组别列什么时候出现
|
||||
|
||||
| 选择情况 | 班级列 | 组别列 |
|
||||
| --- | --- | --- |
|
||||
| 只选 1 个班级、未选组别 | 不出 | 不出 |
|
||||
| 选 ≥2 个班级 | **出** | 未选组别时按数据判断(数据跨多组才出) |
|
||||
| 只选 1 个班级但选 ≥2 个组别 | 不出 | **出** |
|
||||
| 什么都不选(= 全部) | 数据跨 ≥2 个班级才出 | 数据跨 ≥2 个组别才出 |
|
||||
|
||||
- 出列时**连续相同班级 / 组别的单元格会纵向合并**(顺序按 班级 → 组别 → 学号),一个班只占一格;
|
||||
- 也可以用接口参数 `withCls=1` / `withGrp=1` 强制出列(`=0` 强制不出)。
|
||||
|
||||
### 其它形态
|
||||
|
||||
| 表格形态 | 产出 |
|
||||
| --- | --- |
|
||||
| 两行表头(每次考试 + 合格次数) | 上面那套块表(**默认**) |
|
||||
| 成绩对比(每人一行) | 一行一个学生、一列一场考试,成绩取「最新」或「最高」 |
|
||||
| 两者都出 | 第一张块表 + 第二张成绩对比表 |
|
||||
|
||||
### 文件名
|
||||
|
||||
```
|
||||
成绩明细_<试卷名>[_<班级>][_<组别>][_最新成绩]_<YYYYMMDD_HHMMSS>.xlsx
|
||||
成绩明细_<试卷名>[_<班级>][_<组别>][_最新成绩|_最高成绩]_<YYYYMMDD_HHMMSS>.xlsx
|
||||
每次考试_<试卷名>[_<班级>][_<组别>]_<YYYYMMDD_HHMMSS>.xlsx
|
||||
缺考名单_<试卷名>[_<班级>][_<组别>]_<YYYYMMDD_HHMMSS>.xlsx
|
||||
多考试成绩对比_<N>场[_<班级…>][_<组别…>]_<最新成绩|最高分>_<YYYYMMDD_HHMMSS>.xlsx
|
||||
每次考试与成绩对比_<N>场[_<班级…>][_<组别…>]_<YYYYMMDD_HHMMSS>.xlsx # 两者都出
|
||||
```
|
||||
|
||||
### 跟随筛选
|
||||
|
||||
导出**完全跟随页面当前的班级 / 组别筛选**,缺考口径也与页面一致
|
||||
(筛选后名单 − 筛选后已提交,按学号匹配),不会出现"页面上 30 人、导出 50 人"的情况。
|
||||
(筛选后名单 − 筛选后已提交,按学号匹配),不会出现「页面上 30 人、导出 50 人」的情况。
|
||||
|
||||
## 导出缺考名单
|
||||
|
||||
工具栏 **导出缺考**,列为 `学号 / 姓名 / 班级 / 组别`,按学号升序。
|
||||
|
||||
## 打印成绩明细
|
||||
|
||||
成绩明细面板右上角 **打印**,弹窗里可设置:
|
||||
## 打印
|
||||
|
||||
| 选项 | 说明 |
|
||||
| --- | --- |
|
||||
| 打印标题 | 默认「试卷名 + 成绩明细」,可改成学校/考试正式名称 |
|
||||
| 排序方式 | 成绩降序(默认)/ 升序 / 学号 / 提交时间 |
|
||||
| 分组对比 | 按班级或组别分段,段首给出小计(人数/平均/最高/最低/合格人数与合格率) |
|
||||
| 纸张方向 | A4 纵向(列少清晰)或横向(列多不折行) |
|
||||
| 显示名次 | 全表连续编号,不分组也不会因为分段重新从 1 开始 |
|
||||
| 显示「是否合格」列 | 低于合格线的成绩与「不合格」标红,一眼定位 |
|
||||
| 显示考试次数 | 便于发现反复重考的人 |
|
||||
| 附缺考名单 | 成绩表后**另起一页**附缺考名单,带空白备注列供手写 |
|
||||
| 打印标题 | 默认按考试名自动生成,可改成学校 / 考试正式名称 |
|
||||
| 纸张方向 | 多考试打印默认 **横向**(列多不折行),可改纵向 |
|
||||
| 成绩明细的分组对比 | 按班级或组别分段,段首给出小计(人数 / 平均 / 最高 / 最低 / 合格人数与合格率) |
|
||||
| 成绩明细的显示选项 | 显示名次、显示「是否合格」列、显示考试次数、附缺考名单 |
|
||||
|
||||
其它细节:
|
||||
- 表头在**每一页自动重复**,行不会被切断到两页;两行表头都放进 `<thead>`;
|
||||
- 页眉含范围(班级 / 组别)、打印时间、人数、平均分、最高 / 最低、合格人数与合格线;
|
||||
- 页脚含**教师 / 教研组长签字栏与日期**,可直接签字归档。
|
||||
|
||||
- 表头在**每一页自动重复**,行不会被切断到两页;
|
||||
- 页眉含范围(班级/组别)、打印时间、人数、平均分、最高/最低、合格人数与合格线;
|
||||
- 页脚含**教师 / 教研组长签字栏与日期**,可直接签字归档;
|
||||
- 打印走隐藏 iframe 调起,**不会被浏览器的弹窗拦截挡掉**,也不会多开标签页。
|
||||
成绩明细面板右上角的**打印**与导出弹窗里的打印设置是同一套(打印标题、方向、分组对比都在弹窗里改)。
|
||||
|
||||
## 打印缺考名单
|
||||
::: tip 绿底 / 红字要能印出来
|
||||
打印样式里写了 `print-color-adjust: exact`,**不需要**在打印对话框里手动勾选「背景图形」,
|
||||
Chrome / Edge 会照常输出绿底与红字。若仍看不到底纹,检查是否换用了不支持该属性的浏览器。
|
||||
:::
|
||||
|
||||
缺考名单面板右上角 **打印**:按班级分组、班内按学号排序,同样带页眉与签字栏,
|
||||
备注列留空供手写说明(请假、缓考等)。
|
||||
::: tip 缺考名单单独成页
|
||||
勾选「附缺考名单」后,缺考名单工作表会在打印时**另起一页**(不会挤在成绩表底部),便于分开归档。
|
||||
:::
|
||||
|
||||
## 直接调用导出接口
|
||||
|
||||
需要对接其它系统时,可以带参数直接 GET(需已登录):
|
||||
|
||||
```
|
||||
api.php?action=export&projectId=xxx&cls=1&grp=A&mode=latest&split=cls&sort=score_desc&cols=sid,name,score
|
||||
# 成绩明细(每人一行最新 / 最高)
|
||||
api.php?action=export&projectId=xxx&cls=1班,2班&grp=A组&mode=latest&scoreMode=best&sort=score_desc
|
||||
# 「每次考试」块表(多场)
|
||||
api.php?action=export_multi&projectIds=a,b&mode=block&passTimes=1
|
||||
# 单场宽表版式(每人一行,第几次做列名)
|
||||
api.php?action=export_multi&projectIds=a&mode=block&wide=1
|
||||
# 多考试:成绩对比 / 两者都出
|
||||
api.php?action=export_multi&projectIds=a,b&mode=summary&scoreMode=highest
|
||||
api.php?action=export_multi&projectIds=a,b&mode=both
|
||||
# 「多考试打印」用的数据(不下载文件,返回 rows / merges / header_rows / cell_styles)
|
||||
api.php?action=export_multi&projectIds=a,b&mode=block&format=json
|
||||
# 缺考名单
|
||||
api.php?action=export_absent&projectId=xxx
|
||||
```
|
||||
|
||||
| 参数 | 取值 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `projectId` | 试卷 ID | 必填 |
|
||||
| `cls` / `grp` | 班级 / 组别 | 与页面筛选一致 |
|
||||
| `mode` | `latest` | 每人一行最新成绩;缺省导出全部记录 |
|
||||
| `projectId` | 试卷 ID | 必填(`export_multi` 用 `projectIds`,逗号分隔,可只传一场) |
|
||||
| `cls` / `grp` | 班级 / 组别 | 与页面筛选一致;`export_multi` 支持**多选**(逗号分隔),空 = 全部 |
|
||||
| `mode` | `latest` / `all` | `export` 的成绩明细:每人一行(默认,取最新)/ 每次考试一行 |
|
||||
| `scoreMode` | `latest` / `best` | 每人一行的代表成绩:最新(默认)/ 最高 |
|
||||
| `mode`(`export_multi`) | `block` / `summary` / `both` | 每次考试块表(默认)/ 成绩对比 / 两者都出;旧值仍兼容:`matrix`→`summary`、`merged`·`attempts`→`block` |
|
||||
| `wide` | `1` | 单场 `block` 时改用宽表版式(每人一行、第几次做列名) |
|
||||
| `passTimes` | 正整数 | 合格次数达标阈值(默认 1) |
|
||||
| `markBest` | `0` | `=0` 取消「最高分标红」 |
|
||||
| `passRow` | `0` | `=0` 不输出「合格次数」行(也就没有绿底) |
|
||||
| `format` | `json` | 不下载文件,返回 `sheets`(`rows` / `merges` / `header_rows` / `cell_styles`)供打印渲染 |
|
||||
| `withCls` / `withGrp` | `1` / `0` | 强制出 / 不出班级、组别列;缺省按上表规则自动判断 |
|
||||
| `noAbsent` | `1` | 成绩明细不附缺考名单 |
|
||||
| `skipTemp` | `1` | `mode=all` 时排除暂存草稿 |
|
||||
| `includeTemp` | `1` | 每次考试块表保留暂存草稿(标注为 `第N次(草稿)`) |
|
||||
| `sort` | `time` / `sid` / `score_desc` / `score_asc` | 成绩明细排序(块表恒按 班级 → 组别 → 学号 / 学号) |
|
||||
| `split` | `cls` | 按班级拆分多工作表 |
|
||||
| `sort` | `time` / `sid` / `score_desc` / `score_asc` | 排序 |
|
||||
| `cols` | 逗号分隔列名 | 从默认列中挑选 |
|
||||
| `cols` | 逗号分隔列名 | 从默认列中挑选(仅 `export`) |
|
||||
|
||||
`format=json` 返回的 `cell_styles` 是 `行,列 → red | green`,行与列都是 **1-based**;
|
||||
前端据此加红字 / 绿底,合并区间内的非首格继承左上角首格的标记。
|
||||
|
||||
## 相关
|
||||
|
||||
|
||||
@@ -31,9 +31,10 @@ NY 问卷考试系统数据平台是一个**零第三方运行依赖**的 PHP 8
|
||||
| 试卷设置 | 为当前选中的试卷单独设置满分 / 合格率 / 免考名单,试卷间互相隔离 |
|
||||
| 导出 / 打印 | 成绩明细、缺考名单 `.xlsx`;成绩明细按成绩降序打印,支持分组小计、合格标记、附缺考名单、签字栏 |
|
||||
|
||||
### 数据看板 `dashboard.php`
|
||||
### 数据大屏 `dashboard.php`
|
||||
|
||||
大屏看板,适合投屏。支持全屏切换与自动刷新。
|
||||
首页先选试卷,再用卡片列出该卷的班级;点卡片进入该班专属大屏。
|
||||
大屏页支持全屏切换与自动刷新,**没有返回按钮,浏览器后退键也被屏蔽**(只能靠地址栏或关标签页离开)。
|
||||
|
||||
### 随机抽取 `draw.php`
|
||||
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ features:
|
||||
| 页面 | 入口 | 用途 |
|
||||
| --- | --- | --- |
|
||||
| 主系统 | `index.php` | 成绩明细、统计卡片、名单管理、试卷设置、导出与打印 |
|
||||
| 数据看板 | `dashboard.php` | 大屏展示,适合投屏实时监控提交进度 |
|
||||
| 数据大屏 | `dashboard.php` | 首页列出班级入口,点进班级专属大屏(可全屏、自动刷新),适合投屏 |
|
||||
| 随机抽取 | `draw.php` | 从名单或某试卷已提交人员中随机抽取,支持白名单导出 |
|
||||
|
||||

|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
<!DOCTYPE html><html lang="zh-CN"><head><meta charset="utf-8">
|
||||
<title>数据大屏首页(预览)</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="../../assets/style.css">
|
||||
<style>
|
||||
/* 预览页专属:补上 hero 里样式类所需的小件(原页面由 dashboard.php 内联给出) */
|
||||
.brand-text{display:flex;flex-direction:column;gap:2px}
|
||||
.dot{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--border-2);vertical-align:1px}
|
||||
.dot.on{background:var(--ok)}
|
||||
.dot.stale{background:var(--danger)}
|
||||
.spacer{flex:1}
|
||||
.preview-tip{margin:12px 0 0;padding:8px 12px;border:1px dashed var(--border);border-radius:var(--radius);
|
||||
font-size:12px;color:var(--text-3);background:var(--panel-weak,#f7f8fc)}
|
||||
</style></head>
|
||||
<body class="dash dash-home">
|
||||
<div class="wrap">
|
||||
<div class="dash-hero">
|
||||
<div class="brand"><h1 class="brand-title">NY问卷考试系统数据平台</h1></div>
|
||||
<div class="dash-controls">
|
||||
<select id="projectSel"><option value="p1">高一数学月考(31 份)</option></select>
|
||||
<span id="classSelWrap"><select id="classSel" disabled><option value="">请先选问卷</option></select></span>
|
||||
<label class="switch"><input type="checkbox" id="autoRefresh" checked><span></span></label>
|
||||
<select id="intervalSel"><option value="15" selected>15 秒</option></select>
|
||||
<button class="btn" id="btnRefresh">刷新</button>
|
||||
<button class="btn" id="btnFullscreen">⛶ 全屏</button>
|
||||
<a class="btn back" id="linkIndex" href="index.php">← 主系统</a>
|
||||
<a class="btn back" id="linkLogout" href="logout.php">退出</a>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top:14px;font-size:12px;color:var(--text-3);display:flex;align-items:center;gap:6px;flex-wrap:wrap;">
|
||||
<span id="heroSub">共 4 个班级 · 点击卡片进入该班大屏</span>
|
||||
<span class="spacer"></span>
|
||||
最后更新:<span id="lastUpdate">2026-09-27 20:57:25</span><i id="liveDot" class="dot on"></i>
|
||||
</div>
|
||||
<div class="preview-tip">静态预览:这张页面由生产环境 dashboard.php 的 <code>clsCardHtml()</code> 渲染,
|
||||
数据取自 mock 卷王。真实站点上点卡片会整页跳转到 <code>dashboard.php?pid=…&class=…</code>,
|
||||
进入该班独立大屏(那里不再有班级选择、返回主系统与退出,浏览器后退键也被锁住)。</div>
|
||||
<div id="board">
|
||||
<section class="cards" id="boardSummary">
|
||||
<div class="card accent-blue"><span>总人数</span><b>0</b></div>
|
||||
<div class="card ok accent-green"><span>已提交</span><b>0</b></div>
|
||||
<div class="card warn accent-orange"><span>缺考</span><b>0</b></div>
|
||||
<div class="card accent-teal"><span>平均分</span><b>-</b></div>
|
||||
<div class="card accent-indigo"><span>合格率</span><b>-</b></div>
|
||||
</section>
|
||||
<div class="sec-title" id="boardTitle">班级入口 <span class="tag-gray">点击卡片进入该班独立大屏</span></div>
|
||||
<div id="boardBody"><div class="cls-grid"><div class="cls-card" data-cls="高一(1)班" role="button" tabindex="0" title="点击进入「高一(1)班」的独立大屏"><div class="cls-head"><span class="cls-name">高一(1)班</span><span class="cls-go">进入 ›</span></div><div class="cls-kpis"><div class="cls-kpi "><span>总人数</span><b>2</b></div><div class="cls-kpi k-ok"><span>已提交</span><b>2</b></div><div class="cls-kpi "><span>缺考</span><b>0</b></div><div class="cls-kpi "><span>平均分</span><b>81</b></div><div class="cls-kpi k-ok"><span>合格率</span><b>100%</b></div></div><div class="cls-bar"><i style="width:100%;background:var(--ok)"></i></div><div class="cls-sub"><span>提交率 100%</span></div></div><div class="cls-card" data-cls="高一(2)班" role="button" tabindex="0" title="点击进入「高一(2)班」的独立大屏"><div class="cls-head"><span class="cls-name">高一(2)班</span><span class="cls-go">进入 ›</span></div><div class="cls-kpis"><div class="cls-kpi "><span>总人数</span><b>1</b></div><div class="cls-kpi k-ok"><span>已提交</span><b>1</b></div><div class="cls-kpi "><span>缺考</span><b>0</b></div><div class="cls-kpi "><span>平均分</span><b>93</b></div><div class="cls-kpi k-ok"><span>合格率</span><b>100%</b></div></div><div class="cls-bar"><i style="width:100%;background:var(--ok)"></i></div><div class="cls-sub"><span>提交率 100%</span></div></div><div class="cls-card" data-cls="高一(3)班" role="button" tabindex="0" title="点击进入「高一(3)班」的独立大屏"><div class="cls-head"><span class="cls-name">高一(3)班</span><span class="cls-go">进入 ›</span></div><div class="cls-kpis"><div class="cls-kpi "><span>总人数</span><b>1</b></div><div class="cls-kpi k-ok"><span>已提交</span><b>1</b></div><div class="cls-kpi "><span>缺考</span><b>0</b></div><div class="cls-kpi "><span>平均分</span><b>90</b></div><div class="cls-kpi k-ok"><span>合格率</span><b>100%</b></div></div><div class="cls-bar"><i style="width:100%;background:var(--ok)"></i></div><div class="cls-sub"><span>提交率 100%</span></div></div><div class="cls-card" data-cls="高一(4)班" role="button" tabindex="0" title="点击进入「高一(4)班」的独立大屏"><div class="cls-head"><span class="cls-name">高一(4)班</span><span class="cls-go">进入 ›</span></div><div class="cls-kpis"><div class="cls-kpi "><span>总人数</span><b>1</b></div><div class="cls-kpi k-ok"><span>已提交</span><b>1</b></div><div class="cls-kpi "><span>缺考</span><b>0</b></div><div class="cls-kpi "><span>平均分</span><b>76</b></div><div class="cls-kpi k-ok"><span>合格率</span><b>100%</b></div></div><div class="cls-bar"><i style="width:100%;background:var(--ok)"></i></div><div class="cls-sub"><span>提交率 100%</span></div></div></div></div>
|
||||
</div>
|
||||
</div>
|
||||
<script>/* 预览页:把"全屏/刷新"按钮做成 plainly 不可点,仅示意版式 */
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
["#btnFullscreen", "#btnRefresh", "#projectSel", "#classSelWrap"].forEach(function (s) {
|
||||
var el = document.querySelector(s); if (el) el.setAttribute("disabled", "disabled");
|
||||
});
|
||||
});</script>
|
||||
</body></html>
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,7 @@
|
||||
<!DOCTYPE html><html lang="zh-CN"><head><meta charset="utf-8">
|
||||
<title>多考试导出 · 每次考试(两行表头)(预览)</title><style>body{font-family:"Microsoft YaHei","PingFang SC",sans-serif;color:#222;background:#f7f7f7;margin:0;padding:24px}.page{background:#fff;border:1px solid #e3e3e3;border-radius:6px;padding:20px 22px;margin:0 auto 20px;max-width:1100px}.page h2{font-size:16px;margin:0 0 4px}.page .sub{font-size:12px;color:#777;margin:0 0 14px}table.bt{border-collapse:collapse;border:1px solid #999;width:100%;background:#fff;font-size:11px}table.bt td,table.bt th{border:1px solid #999;text-align:center;padding:3px 5px}table.bt th,table.bt thead td{background:#eaeaea;font-weight:700}table.bt thead tr:first-child td{background:#eaeaea}table.bt td.absent{color:#888}table.bt td.max{color:#d0021b;font-weight:700}table.bt td.pass{background:#63c384;font-weight:700;-webkit-print-color-adjust:exact;print-color-adjust:exact}html,body,.pass,.absent,.max{-webkit-print-color-adjust:exact;print-color-adjust:exact}.legend{margin:10px 0 0;font-size:12px;color:#555}.legend i{display:inline-block;width:11px;height:11px;vertical-align:-1px;margin:0 4px 0 12px}.legend .r{color:#d0021b;font-weight:700}.legend .g{background:#63c384;font-weight:700}.sign{margin-top:16px;font-size:12px}</style></head><body>
|
||||
<div class="page"><h2>多考试导出 · 每次考试(两行表头)</h2><p class="sub">合格线 110 分,达 1 次标绿</p>
|
||||
<table class="bt"><thead><tr><td rowspan="2">学号</td><td rowspan="2">姓名</td><td rowspan="2">第几次</td><td colspan="2">第一次月考·数学</td><td colspan="2">第一次月考·英语</td></tr><tr><td>成绩</td><td></td><td>成绩</td><td></td></tr></thead><tbody><tr><td rowspan="5">356001</td><td rowspan="5">张三</td><td rowspan="4">1</td><td>112</td><td></td><td class="max">112</td><td></td></tr><tr><td>100</td><td></td><td>99</td><td></td></tr><tr><td class="max">136</td><td></td><td></td><td></td></tr><tr><td>127</td><td></td><td></td><td></td></tr><tr><td>合格次数</td><td class="pass">3</td><td></td><td class="pass">1</td><td></td></tr><tr><td rowspan="4">356002</td><td rowspan="4">李四</td><td rowspan="3">1</td><td></td><td></td><td>130</td><td></td></tr><tr><td></td><td></td><td>129</td><td></td></tr><tr><td></td><td></td><td class="max">133</td><td></td></tr><tr><td>合格次数</td><td>0</td><td></td><td class="pass">3</td><td></td></tr><tr><td rowspan="2">356003</td><td rowspan="2">王五</td><td>1</td><td class="max">95</td><td></td><td colspan="2" class="absent">未考</td></tr><tr><td>合格次数</td><td>0</td><td></td><td></td><td></td></tr></tbody></table>
|
||||
<p class="legend">标记说明:<span class="r">最高分</span> 标红、<i class="r">红字</i>;<span class="g">合格次数</span> 始终显示(含 0 次),达 1 次标绿、<i class="g">绿底</i>;未达标显示次数、不标绿。
|
||||
<p class="sign">教师签字:______________ 教研组长签字:______________ 日期:____________</p>
|
||||
</div></body></html>
|
||||
@@ -0,0 +1,7 @@
|
||||
<!DOCTYPE html><html lang="zh-CN"><head><meta charset="utf-8">
|
||||
<title>单场导出 · 每次考试(每人一行的宽表)(预览)</title><style>body{font-family:"Microsoft YaHei","PingFang SC",sans-serif;color:#222;background:#f7f7f7;margin:0;padding:24px}.page{background:#fff;border:1px solid #e3e3e3;border-radius:6px;padding:20px 22px;margin:0 auto 20px;max-width:1100px}.page h2{font-size:16px;margin:0 0 4px}.page .sub{font-size:12px;color:#777;margin:0 0 14px}table.bt{border-collapse:collapse;border:1px solid #999;width:100%;background:#fff;font-size:11px}table.bt td,table.bt th{border:1px solid #999;text-align:center;padding:3px 5px}table.bt th,table.bt thead td{background:#eaeaea;font-weight:700}table.bt thead tr:first-child td{background:#eaeaea}table.bt td.absent{color:#888}table.bt td.max{color:#d0021b;font-weight:700}table.bt td.pass{background:#63c384;font-weight:700;-webkit-print-color-adjust:exact;print-color-adjust:exact}html,body,.pass,.absent,.max{-webkit-print-color-adjust:exact;print-color-adjust:exact}.legend{margin:10px 0 0;font-size:12px;color:#555}.legend i{display:inline-block;width:11px;height:11px;vertical-align:-1px;margin:0 4px 0 12px}.legend .r{color:#d0021b;font-weight:700}.legend .g{background:#63c384;font-weight:700}.sign{margin-top:16px;font-size:12px}</style></head><body>
|
||||
<div class="page"><h2>单场导出 · 每次考试(每人一行的宽表)</h2><p class="sub">第一次月考·数学 · 合格线 110 分,达 1 次标绿</p>
|
||||
<table class="bt"><thead><tr><td>学号</td><td>姓名</td><td>第1次</td><td>第2次</td><td>第3次</td><td>第4次</td><td>合格次数</td></tr></thead><tbody><tr><td>356001</td><td>张三</td><td>112</td><td>100</td><td class="max">136</td><td>127</td><td class="pass">3</td></tr><tr><td>356002</td><td>李四</td><td></td><td></td><td></td><td></td><td>0</td></tr><tr><td>356003</td><td>王五</td><td class="max">95</td><td></td><td></td><td></td><td>0</td></tr></tbody></table>
|
||||
<p class="legend">标记说明:<span class="r">最高分</span> 标红、<i class="r">红字</i>;<span class="g">合格次数</span> 始终显示(含 0 次),达 1 次标绿、<i class="g">绿底</i>;未达标显示次数、不标绿。
|
||||
<p class="sign">教师签字:______________ 教研组长签字:______________ 日期:____________</p>
|
||||
</div></body></html>
|
||||
@@ -0,0 +1,287 @@
|
||||
{
|
||||
"block": {
|
||||
"title": "多考试导出 · 每次考试(两行表头)",
|
||||
"sheet": {
|
||||
"rows": [
|
||||
[
|
||||
"学号",
|
||||
"姓名",
|
||||
"第几次",
|
||||
"第一次月考·数学",
|
||||
"",
|
||||
"第一次月考·英语",
|
||||
""
|
||||
],
|
||||
[
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"成绩",
|
||||
"",
|
||||
"成绩",
|
||||
""
|
||||
],
|
||||
[
|
||||
"356001",
|
||||
"张三",
|
||||
"1",
|
||||
"112",
|
||||
"",
|
||||
"112",
|
||||
""
|
||||
],
|
||||
[
|
||||
"",
|
||||
"",
|
||||
"2",
|
||||
"100",
|
||||
"",
|
||||
"99",
|
||||
""
|
||||
],
|
||||
[
|
||||
"",
|
||||
"",
|
||||
"3",
|
||||
"136",
|
||||
"",
|
||||
"",
|
||||
""
|
||||
],
|
||||
[
|
||||
"",
|
||||
"",
|
||||
"4",
|
||||
"127",
|
||||
"",
|
||||
"",
|
||||
""
|
||||
],
|
||||
[
|
||||
"",
|
||||
"",
|
||||
"合格次数",
|
||||
"3",
|
||||
"",
|
||||
"1",
|
||||
""
|
||||
],
|
||||
[
|
||||
"356002",
|
||||
"李四",
|
||||
"1",
|
||||
"",
|
||||
"",
|
||||
"130",
|
||||
""
|
||||
],
|
||||
[
|
||||
"",
|
||||
"",
|
||||
"2",
|
||||
"",
|
||||
"",
|
||||
"129",
|
||||
""
|
||||
],
|
||||
[
|
||||
"",
|
||||
"",
|
||||
"3",
|
||||
"",
|
||||
"",
|
||||
"133",
|
||||
""
|
||||
],
|
||||
[
|
||||
"",
|
||||
"",
|
||||
"合格次数",
|
||||
"0",
|
||||
"",
|
||||
"3",
|
||||
""
|
||||
],
|
||||
[
|
||||
"356003",
|
||||
"王五",
|
||||
"1",
|
||||
"95",
|
||||
"",
|
||||
"未考",
|
||||
""
|
||||
],
|
||||
[
|
||||
"",
|
||||
"",
|
||||
"合格次数",
|
||||
"0",
|
||||
"",
|
||||
"",
|
||||
""
|
||||
]
|
||||
],
|
||||
"merges": [
|
||||
[
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
1
|
||||
],
|
||||
[
|
||||
1,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
[
|
||||
1,
|
||||
3,
|
||||
2,
|
||||
3
|
||||
],
|
||||
[
|
||||
1,
|
||||
4,
|
||||
1,
|
||||
5
|
||||
],
|
||||
[
|
||||
1,
|
||||
6,
|
||||
1,
|
||||
7
|
||||
],
|
||||
[
|
||||
3,
|
||||
1,
|
||||
7,
|
||||
1
|
||||
],
|
||||
[
|
||||
3,
|
||||
2,
|
||||
7,
|
||||
2
|
||||
],
|
||||
[
|
||||
3,
|
||||
3,
|
||||
6,
|
||||
3
|
||||
],
|
||||
[
|
||||
8,
|
||||
1,
|
||||
11,
|
||||
1
|
||||
],
|
||||
[
|
||||
8,
|
||||
2,
|
||||
11,
|
||||
2
|
||||
],
|
||||
[
|
||||
8,
|
||||
3,
|
||||
10,
|
||||
3
|
||||
],
|
||||
[
|
||||
12,
|
||||
6,
|
||||
12,
|
||||
7
|
||||
],
|
||||
[
|
||||
12,
|
||||
1,
|
||||
13,
|
||||
1
|
||||
],
|
||||
[
|
||||
12,
|
||||
2,
|
||||
13,
|
||||
2
|
||||
],
|
||||
[
|
||||
12,
|
||||
3,
|
||||
12,
|
||||
3
|
||||
]
|
||||
],
|
||||
"header_rows": 2,
|
||||
"cell_styles": {
|
||||
"3,6": "red",
|
||||
"5,4": "red",
|
||||
"7,4": "green",
|
||||
"7,6": "green",
|
||||
"10,6": "red",
|
||||
"11,6": "green",
|
||||
"12,4": "red"
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"pass_line": 110,
|
||||
"pass_times": 1
|
||||
}
|
||||
},
|
||||
"wide": {
|
||||
"title": "单场导出 · 每次考试(每人一行的宽表)",
|
||||
"sheet": {
|
||||
"rows": [
|
||||
[
|
||||
"学号",
|
||||
"姓名",
|
||||
"第1次",
|
||||
"第2次",
|
||||
"第3次",
|
||||
"第4次",
|
||||
"合格次数"
|
||||
],
|
||||
[
|
||||
"356001",
|
||||
"张三",
|
||||
"112",
|
||||
"100",
|
||||
"136",
|
||||
"127",
|
||||
"3"
|
||||
],
|
||||
[
|
||||
"356002",
|
||||
"李四",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"0"
|
||||
],
|
||||
[
|
||||
"356003",
|
||||
"王五",
|
||||
"95",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"0"
|
||||
]
|
||||
],
|
||||
"merges": [],
|
||||
"header_rows": 1,
|
||||
"cell_styles": {
|
||||
"2,5": "red",
|
||||
"2,7": "green",
|
||||
"4,3": "red"
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"pass_line": 110,
|
||||
"pass_times": 1,
|
||||
"exam_name": "第一次月考·数学"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user