Files
ouc_latex_template/试卷
laoyang 42c1394aec 答案卷抬头改为一行一项,修复长学院名重叠 #22
## 用户诉求

「评分标准最开始不是有个表格吗,里面有开课学院什么的,如果学院名字太长,
就和后面课程名称重合在一起了。看看怎么解决。我建议一行一个信息,
因为这个又不怕长,如果太长,一行都放不下,就直接换行。」

## 现象(已复现并量化)

`dept` 填超长值后,pymupdf 读出:

    开课学院:(70.87~123.37)  值:(123.37~406.87)

而第二格「课程名称」本该从 216.0 开始 ⇒ **重叠 190.87bp**,
把「课程名称 / 试卷类型」整个压住。

⚠️ **编译完全不报错,也没有 Overfull**(rc=0 over=0)。
`\makebox` 内容溢出盒外时 TeX 不认为是坏行。这类 bug 只能靠
量 span 坐标发现,看日志发现不了。

## 根因

`\ouckey@inforow` 用三个 `\makebox[0.3333\linewidth][l]` 并排。
`\makebox` 是**不可断盒子**:
- 内容比盒宽短 → 左对齐(正常)
- 内容比盒宽长 → **直接溢出盒外,压到右边一格**(就是 bug)
- 盒内中文**不能换行**(LR 模式,不做段落断行)

⇒ 三格布局对短字段友好,对长字段必然重叠。

## 改动一:一行一项

    \newcommand{\ouckey@inforow}[2]{%
      \ouckey@ifempty{#2}{}{%
        {\fontsize{10.5bp}{15bp}\selectfont
         \par\noindent\textbf{#1:}#2\par}}}

调用点从「三参数一组」改成「两参数一行」,共 9 项:
课程名称 / 开课学院 / 学生学院 / 年级专业 / 试卷类型 / 考试方式 /
任课教师 / 命题人 / 满分。顺序按"读者关心程度"排。

行距收紧到 15bp(`\Fivhao` 基线距是 16bp)—— 抬头是查阅信息,
不需要正文行距;9 行省约 52bp,将近 3 行正文。

## 改动二:附带修掉一个旧版就有的判空 bug

**旧实现**:
    \newcommand{\ouckey@ifempty}[1]{%
      \if\relax\detokenize{#1}\relax ... }
调用 `\ouckey@ifempty{\ouckey@dept}{空}{非空}`。
`\detokenize` **不展开参数**,看到的是字符串 `\ouckey@dept`(宏名),
永远非空 ⇒ 判空永远失败。

后果:`dept = {}` 时抬头印出孤立的「开课学院:」,后面没有值。
这是旧版就有的 bug(三格布局下不明显),改成一行一项后暴露。

**修法**:在 `\define@key` 里就规范化空值,新增
    \newcommand{\ouckey@setkey}[2]{%
      \if\relax\detokenize{#2}\relax \def#1{}\else \def#1{#2}\fi}
13 个 key 全改走它。

⚠️ 试过「先 `\edef` 展开再 `\detokenize`」的写法,报
   `! Incomplete \iffalse` —— `\if...\else...\fi` 被 `\expandafter`
   链打散,TeX 匹配 `\fi` 时错位。这类宏层展开的修补太脆,放弃。
⚠️ `\ouckey@setkey` 必须定义在 `\define@key` **之前**,否则 undefined。

## 验证

### 三个场景

| 场景 | 结果 |
|---|---|
| 正常(学院名 12 字) | 9 项齐全,无重叠,无越界 |
| 长(含括号说明,约 40 字) | 单行排到 x=406.90,无重叠(下面没有格子可压) |
| 极长(约 70 字) | **自动换行成两行**,第二行缩进对齐,右缘正好 524.40 |
| 留空(dept/college/major 全空) | 三项**整项不印**,不留空行 |

### 编译

    试卷题型示例        6 页  err=0 over=0
    参考答案与评分标准  4 页  err=0 over=0

全库 `bash build.sh all` → **13/13 通过,0 失败**。

### 页数变化

答案卷 3 页 → 4 页。抬头从 3 行变 9 行,是「一行一项」的必然代价。
**已向用户确认,接受 4 页**(第 4 页只有说明文字末尾 2 行 + 签字行)。

## 示例文件未改

`参考答案与评分标准示例.tex` 测试后已还原,`git diff` 为空。
只改 `ouckey.sty` 一个文件。
2026-10-29 22:58:34 +08:00
..

试卷 —— 试卷与参考答案 LaTeX 模板

中国海洋大学期末考试试卷与参考答案及评分标准的 XeLaTeX 模板。 两份模板均不含真题,题目与分值都是示意,按教学大纲替换即可。

样张是《数字逻辑》2025 秋的一份完整虚构 A 卷:16 类题型(填空 / 选择 / 判断 / 化简 / 分析 / 设计 / 时序 / 计数器 / 状态机 / 存储器 / ADC-DAC / Verilog / 综合设计 …)+ 对应参考答案与评分标准(8 大题 / 满分 100)。 题目是按数字逻辑课程内容真编的、答案算过是对的,不是「略」或「×××」—— 这样既能看清版式,也能看出各题型的排版难度(比如卡诺图、时序波形图 都是 TikZ 内联画的)。

与 课程教学日历/、成绩构成说明/、 试卷归档封面/ 是同一门课,四份一起看是自洽的。 唯一故意留空的是命题人 / 审核人 / 各题得分栏 —— 那是要签字担责的, 编名字上去容易被误当真实署名。

文件

文件 说明
oucexam.sty 试卷版式包。纸张 195×270mm(学校专用试卷纸),含装订栏、成绩表、页脚
ouckey.sty 答案与评分标准版式包。默认 A4;加 exampaper 选项则与试卷同纸同边距
试卷题型示例.tex 试卷范例,16 类题型,6 页
参考答案与评分标准示例.tex 答案范例,8 大题 / 满分 100,3 页

编译

xelatex 试卷题型示例.tex
xelatex 试卷题型示例.tex       # 跑两遍,第二遍才能取到正确总页数(lastpage)

必须用 XeLaTeX(fontspec + xeCJK),pdflatex 编译不过。 两份 .tex 都在本目录内自包含,不依赖任何图片文件(示例配图是 TikZ 内联画的)。

试卷模板要点

纸张、页边距、行距、装订栏位置、页脚样式都已在 oucexam.sty 里按原卷实测值定好, 一般只改 \examsetup 那一块(下例是样张实际用的虚构值):

\examsetup{
  year      = {2025},        % 学年(会自动印成 2025—2026)
  term      = {秋},           % 秋 / 春
  course    = {数字逻辑},
  college   = {信息科学与工程学院},
  type      = {A},            % 卷头「试卷类型:A 卷」
  foottype  = {},             % 页脚课程名后是否再印类型字母,空=不印
  proposer  = {},             % 命题人
  reviewer  = {},             % 审核人
  mode      = {闭卷},
  allowed   = {无},           % 允许携带的物品
  nsec      = {16},           % 大题数,成绩表自动按 nsec+1 栏等分
}
  • proposer / reviewer 样张里故意留空:命题人、审核人是要签字担责的, 编一个名字上去容易被误当真实署名。留空时模板自动不印该项、不留空横线。
  • type 与 foottype 互不影响:前者只管卷头,后者只管页脚。 原卷 A 卷页脚没印字母、B 卷印了 B,这是出卷人手工差异,不是规则。
  • 大题数变了必须同步改 nsec,否则成绩表格子会错位。

答案模板要点

\keysetup{
  year = {2025}, term = {秋}, course = {数字逻辑}, type = {A},
  dept = {计算机科学与技术学院}, college = {信息科学与工程学院},
  major = {计算机科学与技术专业 \TNR{2023} 级},
  teacher = {张远航}, examiner = {张远航},
  mode = {闭卷、笔试}, total = {100},
}

如实现在试卷同一张纸上印,把 \usepackage{ouckey} 改成 \usepackage[exampaper]{ouckey}。

体例四条(学校没有统一模板,按国内高校通行做法拟定):

  1. 抬头信息齐全,留空的项自动不印、不留空横线
  2. 客观题答案集中列(\objkeys{C,B,A,...},每行 6 个自动换行),附统一给分规则
  3. 主观题内嵌分步分值(\pt{2}),阅卷时批到哪里看到哪里
  4. 每个大题末尾给【评分标准】\scoring{...}

主观题内嵌分值是有意为之:阅卷是流水作业,分值必须和答案文字贴在一起, 集中写在末尾会让批卷人来回翻页。

文末 \keytotal{20,10,12,12,12,16,8,10} 是分值汇总表,用于阅卷前核对 「各大题相加 = 满分」。签名栏 \keysign 只留命题人一处。

书写注意

  • 题干内部换行用 \\*,不要用裸 \\。裸 \\ 语义是"允许在此断页", 题干会被切到上下两页,学生看到半句话。
  • 数字、英文用 \TNR{...} 包起来(内部显式 \normalfont 收尾)。 裸用字体切换命令会让字体状态泄漏到后续段落。
  • \keyitem{题号}{分值}{答案正文} 的参数里不要嵌 tabular / tikzpicture—— 这些环境的 & 与 \\ 会被当成参数分隔符,报 File ended while scanning。 表格和图写在 \keyitem 之后。