# 导出与打印 工具栏下方只有一个 **导出** 按钮,所有导出与打印的选项都收在这个弹窗里,不再散落多个小按钮。 选项在你打开弹窗前就配好了会**自动记住**(存本地),下次打开就是上次的设置。 > 生成的是 `.xlsx`:零依赖,仓库内自行实现 XLSX 写入,没有 `zip` 扩展也能用。 ## 导出弹窗 | 分区 | 内容 | | --- | --- | | **导出内容** | 成绩明细 / 每次考试 / 缺考名单 / 多考试对比(四选一,选中后下方分区跟着变) | | **统计范围** | 班级 / 组别多选(不选 = 全部,按住 `Ctrl` / `⌘` 多选) | | **成绩口径与列** | 每人成绩(最新 / 最高)、排序、出表方式、按班级分工作表、附缺考名单 | | **多考试对比** | 表格形态、对比成绩、勾选要对比的考试 | | **附加内容** | 附缺考名单(成绩明细 / 每次考试 / 多考试对比 都出工作表) | | **标记与合格次数** | 合格次数阈值、最高分标红、输出「合格次数」行 | | **打印设置** | 纸张方向、打印标题 | - 分区随「导出内容」显隐:选 **缺考名单** 时只保留范围与打印设置; 选 **多考试对比** 时才出现考试勾选表; - **附加内容** 与 **标记与合格次数** 是三类成绩表共用的,不随导出内容消失; 「按班级分工作表」只有成绩明细支持(置灰不可勾选); - 弹窗底部有**一句话汇总**(导什么、哪些考试、多大范围),导错了一眼能看出来; - 打印走隐藏 iframe 调起,**不会被浏览器弹窗拦截挡掉**,也不会多开标签页。 ### 成绩明细:每人最新成绩 / 最高成绩 **默认按每人最新成绩显示**(最近一次真实提交),可选 **最高成绩**(该生在这些考试里的最高分)。 | 选项 | 效果 | | --- | --- | | 每人成绩 | `最新成绩`(默认)/ `最高成绩` —— 每人一行时的代表成绩 | | 排序 | `按提交时间` / `按学号` / `按成绩降序` / `按成绩升序` | | 出表方式 | `每人一行(汇总)`(默认)/ `每次考试一行(明细)`:明细模式保留每位学生的历史提交 | | 附缺考名单 | 默认开;只导成绩时取消勾选(接口 `noAbsent=1`)。**每次考试 / 多考试对比 也支持**,口径为「名单里有、所选考试全都没交」 | | 按班级分工作表 | 一个班级一个工作表(xlsx 多工作表) | 默认列:`学号 / 姓名 / 班级 / 组别 / 成绩 / 最高分 / 考试次数 / 最近提交时间 / 考试时长 / 考试时长(秒)`。 ## 「每次考试」块表(多场对比,主推格式) 勾选多场考试,选 **两行表头** 形态。**一列「第几次」被所有考试共用**(逐行写 1、2、3…,不合并), 每场考试占 **1 列**,学生块末尾多一行 **合格次数**。 | 学号 | 姓名 | 第几次 | 第一次月考·数学 | 第一次月考·英语 | | --- | --- | --- | --- | --- | | | | | 成绩 | 成绩 | | (合并) | (合并) | 1 | 112 | 130 | | (合并) | (合并) | 2 | 100 | 129 | | (合并) | (合并) | 3 | **136** | **133** | | (合并) | (合并) | **合格次数** | 3 | 3 | | 356002 | 李四 | 1 | (合并)**未考** | 128 | | (合并) | (合并) | **合格次数** | | 1 | 规则: - **学生块高度** = 该生在所有勾选考试里最多的那次次数 + 1(末行是合格次数); - **学号 / 姓名**按学生块纵向合并;**第几次**逐行写各自的次序号(1、2、3…),**不合并** ——合并会把 2、3 吞掉只剩 1; - **每场考试占 1 列**:第 1 行是考试名、第 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` 强制不出)。 ### 其它形态 | 表格形态 | 产出 | | --- | --- | | 两行表头(每次考试 + 合格次数) | 上面那套块表(**默认**) | | 成绩对比(每人一行) | 一行一个学生、一列一场考试,成绩取「最新」或「最高」 | | 两者都出 | 第一张块表 + 第二张成绩对比表 | ### 文件名 ``` 成绩明细_<试卷名>[_<班级>][_<组别>][_最新成绩|_最高成绩]_.xlsx 每次考试_<试卷名>[_<班级>][_<组别>]_.xlsx 缺考名单_<试卷名>[_<班级>][_<组别>]_.xlsx 多考试成绩对比_场[_<班级…>][_<组别…>]_<最新成绩|最高分>_.xlsx 每次考试与成绩对比_场[_<班级…>][_<组别…>]_.xlsx # 两者都出 ``` ### 跟随筛选 导出**完全跟随页面当前的班级 / 组别筛选**,缺考口径也与页面一致 (筛选后名单 − 筛选后已提交,按学号匹配),不会出现「页面上 30 人、导出 50 人」的情况。 ## 打印 | 选项 | 说明 | | --- | --- | | 打印标题 | 默认按考试名自动生成,可改成学校 / 考试正式名称 | | 纸张方向 | 多考试打印默认 **横向**(列多不折行),可改纵向 | | 成绩明细的分组对比 | 按班级或组别分段,段首给出小计(人数 / 平均 / 最高 / 最低 / 合格人数与合格率) | | 成绩明细的显示选项 | 显示名次、显示「是否合格」列、显示考试次数、附缺考名单 | - 表头在**每一页自动重复**,行不会被切断到两页;两行表头都放进 ``; - 页眉含范围(班级 / 组别)、打印时间、人数、平均分、最高 / 最低、合格人数与合格线; - 页脚含**教师 / 教研组长签字栏与日期**,可直接签字归档。 成绩明细面板右上角的**打印**与导出弹窗里的打印设置是同一套(打印标题、方向、分组对比都在弹窗里改)。 ::: tip 绿底 / 红字要能印出来 打印样式里写了 `print-color-adjust: exact`,**不需要**在打印对话框里手动勾选「背景图形」, Chrome / Edge 会照常输出绿底与红字。若仍看不到底纹,检查是否换用了不支持该属性的浏览器。 ::: ::: tip 缺考名单单独成页 勾选「附缺考名单」后,缺考名单工作表会在打印时**另起一页**(不会挤在成绩表底部),便于分开归档。 ::: ## 直接调用导出接口 需要对接其它系统时,可以带参数直接 GET(需已登录): ``` # 成绩明细(每人一行最新 / 最高) 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 | 必填(`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` | 按班级拆分多工作表 | | `cols` | 逗号分隔列名 | 从默认列中挑选(仅 `export`) | `format=json` 返回的 `cell_styles` 是 `行,列 → red | green`,行与列都是 **1-based**; 前端据此加红字 / 绿底,合并区间内的非首格继承左上角首格的标记。 ## 相关 - [成绩明细与统计口径](./scores.md) - [接口一览](../dev/api.md)