新增试卷归档目录 LaTeX 模板 #7

把「附件2:信息科学与工程学院归档目录(理论课).doc」做成 LaTeX 模板,
落在 试卷归档目录/。版式逐项照原 .doc 还原,尺寸全部注明换算过程。

- oucgddir.sty:A4、表宽 150.81mm、13 行固定行高、单元格宏
- 试卷归档目录.tex:12 项核对清单
- README.md:用法 / 版式参数表 / 实测数据 / 踩坑记录
- 根 README.md、fonts.tex:模板清单加一项,「七个」改「八个」

与原稿实测对比(pymupdf 读 PDF):
  表格竖线 x Δ ≤ 0.001mm,横线 y Δ ≤ 0.006mm
  32 行文字水平中心 Δ ≤ 0.11pt,字号 24/18/12/10.45 全部精确
  编译 1 页,零 Overfull / Underfull / 缺字

踩到并解决的五个坑:
  1. \fontsize 必须用 bp(TeX pt 比 PostScript pt 大 0.36%,24pt 实测 23.91)
  2. xeCJK 吞连续半角空格 → 标题字间用 \gdgap 手动 kern 24bp
  3. xeCJK 默认 PunctStyle=quanjiao 会挤压全角括号,使含括号的行整行
     右移 4.23pt → 必须 \xeCJKsetup{PunctStyle=plain}
  4. tabularray 把线宽算进列宽、ht 不含 hline 线宽、boxes 比 Σwd 多
     0.4945pt → 三处都要实测标定
  5. 单元格整体下移只有「尾部 \vspace*」有效,顶部 \vspace*/rule 会被
     首行 ascent 吃掉,\raisebox 被 m 居中抵销

字体:方正楷体_GB2312(商业,不可分发)→ OUC Kai(霞鹜文楷子集,OFL 1.1),
西文 Times New Roman → TeX Gyre Termes。字宽逐字相同(60.00 / 120.00pt 全等)。
This commit is contained in:
2026-10-27 07:51:10 +08:00
parent 8aa979739a
commit 8fa44b138c
6 changed files with 724 additions and 2 deletions
+2 -1
View File
@@ -8,6 +8,7 @@
|---|---|---| |---|---|---|
| [`试卷/`](试卷/) | 期末考试**试卷**、**参考答案及评分标准**两套模板 | `试卷题型示例.tex`、`参考答案与评分标准示例.tex` | | [`试卷/`](试卷/) | 期末考试**试卷**、**参考答案及评分标准**两套模板 | `试卷题型示例.tex`、`参考答案与评分标准示例.tex` |
| [`试卷归档封面/`](试卷归档封面/) | 信息科学与工程学部**试卷归档封面**(理论课) | `试卷归档封面.tex` | | [`试卷归档封面/`](试卷归档封面/) | 信息科学与工程学部**试卷归档封面**(理论课) | `试卷归档封面.tex` |
| [`试卷归档目录/`](试卷归档目录/) | 信息科学与工程学部**试卷归档目录**(理论课,12 项核对清单) | `试卷归档目录.tex` |
| [`年度考核登记表/`](年度考核登记表/) | 教职工**年度考核登记表** | `年度考核登记表.tex` | | [`年度考核登记表/`](年度考核登记表/) | 教职工**年度考核登记表** | `年度考核登记表.tex` |
| [`劳务发放说明表/`](劳务发放说明表/) | **劳务发放说明表** | `劳务发放说明表.tex` | | [`劳务发放说明表/`](劳务发放说明表/) | **劳务发放说明表** | `劳务发放说明表.tex` |
| [`课程执行大纲/`](课程执行大纲/) | 本科**课程教学执行大纲、教学日历** | `课程执行大纲.tex` | | [`课程执行大纲/`](课程执行大纲/) | 本科**课程教学执行大纲、教学日历** | `课程执行大纲.tex` |
@@ -28,7 +29,7 @@ xelatex slides.tex # 跑两遍,第二遍才能取到正确的目录、
## 说明 ## 说明
- **字体单一来源**:全库字体集中在根目录 [`fonts/`](fonts/),由 [`fonts.tex`](fonts.tex) 统一加载。七个模板通过 `\input{../fonts.tex}` 取字体,**不自带字体、不依赖系统字体**——换机器(Windows / macOS / Linux / Overleaf)编译结果一致。 - **字体单一来源**:全库字体集中在根目录 [`fonts/`](fonts/),由 [`fonts.tex`](fonts.tex) 统一加载。八个模板通过 `\input{../fonts.tex}` 取字体,**不自带字体、不依赖系统字体**——换机器(Windows / macOS / Linux / Overleaf)编译结果一致。
- **全部开源可商用**:无方正、无 SimSun / SimHei / KaiTi / FangSong、无 Times New Roman、无微软雅黑。用的是思源宋体/黑体、霞鹜文楷、朱雀仿宋、TeX Gyre Termes、鸿蒙 HarmonyOS Sans(各字体授权见 [`fonts/LICENSE`](fonts/LICENSE),来源与字符集见 [`fonts/README.md`](fonts/README.md))。 - **全部开源可商用**:无方正、无 SimSun / SimHei / KaiTi / FangSong、无 Times New Roman、无微软雅黑。用的是思源宋体/黑体、霞鹜文楷、朱雀仿宋、TeX Gyre Termes、鸿蒙 HarmonyOS Sans(各字体授权见 [`fonts/LICENSE`](fonts/LICENSE),来源与字符集见 [`fonts/README.md`](fonts/README.md))。
- **每个子目录自包含**:样式文件(`.sty` / `.cls`)、图片都在各目录内,编译时不需要额外的宏包搜索路径;只有字体是共享的上层目录。 - **每个子目录自包含**:样式文件(`.sty` / `.cls`)、图片都在各目录内,编译时不需要额外的宏包搜索路径;只有字体是共享的上层目录。
- **各目录的 `README.md`** 写明该模板的用法、可改参数、版式数据来源与书写注意事项,改之前先看。 - **各目录的 `README.md`** 写明该模板的用法、可改参数、版式数据来源与书写注意事项,改之前先看。
+1 -1
View File
@@ -1,7 +1,7 @@
%====================================================================== %======================================================================
% oucfonts.tex —— 中国海洋大学模板库的公共字体入口 % oucfonts.tex —— 中国海洋大学模板库的公共字体入口
% %
% 本文件是仓库内**唯一**允许声明字体的地方。七个模板全部通过 % 本文件是仓库内**唯一**允许声明字体的地方。八个模板全部通过
% \input{../fonts.tex} % \input{../fonts.tex}
% 取字体,不再各自写 \setCJKmainfont / \setmainfont。 % 取字体,不再各自写 \setCJKmainfont / \setmainfont。
% %
+199
View File
@@ -0,0 +1,199 @@
# 试卷归档目录 —— 信息科学与工程学部试卷归档目录(理论课)
信息科学与工程学部**试卷归档目录**的 XeLaTeX 模板。原文件是学院/学部下发的
`.doc` 表(12 项核对清单),本目录把它做成可直接编译的 LaTeX 版。
> **改名说明**:原文件名为「附件2:信息科学与工程学院归档目录(理论课)」,
> 内文写的是「归档目录」、未出现单位名。按现行建制已统一为 **学部**,
> 目录名、文件名同步。内文标题保持原文「归 档 目 录」(四字间隔一个字宽)。
> 与 [`试卷归档封面/`](../试卷归档封面/) 的关系:两件是**同一套归档材料**的
> 两个附件的原件配套 —— 附件1 是封面(随卷装订、11 行表单),本目录是
> 附件2(装袋前逐项核对的清单、12 项勾选表)。版式上都照原 `.doc` 1:1 还原,
> 但一个是 A4 表单、一个是 A4 居中表格,互不依赖。
## 文件
| 文件 | 说明 |
|---|---|
| `oucgddir.sty` | 版式包。A4、表宽 150.64mm、13 行固定行高,每项尺寸都附换算过程 |
| `试卷归档目录.tex` | 正文入口(12 项清单写在这里,增删改归档项只改这个文件) |
| `试卷归档目录.pdf` | 成品样张 |
## 编译
```bash
xelatex 试卷归档目录.tex
```
必须用 **XeLaTeX**(fontspec + xeCJK),pdflatex 编译不过。
自包含,不依赖任何图片。实测 1 页,零警告(无 Overfull / Underfull / 缺字)。
## 用法
正文就是一张表,加行改行即可:
```latex
\begin{gdtable}
\gdhead{序号} & \gdhead{内容} & \gdheadIII \\
\gdno{1} & \gditem{考试签到表} & \\
\gdno{2} & \gditem{监考记录} & \\
% …… 照此继续
\end{gdtable}
```
可用的单元格宏:
| 宏 | 用途 | 字号/字形 |
|---|---|---|
| `\gdno{1}` | 序号列 | 楷体 12pt 粗 |
| `\gditem{考试签到表}` | 内容列 | 楷体 12pt |
| `\gdhead{序号}` | 表头单段格(序号、内容两列) | 楷体 18pt 粗 |
| `\gdheadIII` | 表头第三格,**自带**「标注」+ 小字两段 | 18pt 粗 + 10.45pt |
| `\gdnote{...}` | 单独排一行小字(10.45pt) | 楷体 10.45pt |
标题用 `\gdtitle{归\gdgap 档\gdgap 目\gdgap 录}` —— **`\gdgap` 不能省**,
原因见下面第 3 条。
## 版式参数
全部照原 `.doc` 实测值,未做主观调整:
| 项目 | 值 | 来源 |
|---|---|---|
| 纸张 | A4 210×297mm | `pgSz` 11906×16838 twips |
| 页边距 | 上下 25.40mm、左右 29.599mm | `pgMar` top/bottom 1440 twips;左右经实测标定,见下 |
| 表宽 | 150.81mm | `tblGrid` 合计 8540 twips = 150.64mm,加列取整余量 |
| 列宽 | 23.072 + 77.346 + 50.218 mm | `gridCol` 1308 / 4385 / 2847 twips |
| 单元格内边距 | 左右 1.905mm、上下 0 | `tblCellMar` 108 twips |
| 边框 | 0.5pt 实线 | `w:sz=4`(1/8pt 单位) |
| 行高 | 表头 20.549mm、中间 12 行 13.758mm、末行 14.164mm | `trHeight` 1165 / 780 / 803 twips,`hRule=exact` |
| 标题 | 楷体 24pt,首行缩进 46.55mm | `firstLine` 2640 twips |
| 表头 | 楷体 18pt 粗 | `w:sz=36` + `w:b` |
| 表头小注 | 楷体 10.45pt | `w:szCs=21`(未设 `w:sz`,Word 退回 10.5pt) |
| 序号列 | 楷体 12pt 粗 | `w:sz=24` + `w:b` |
| 内容列 | 楷体 12pt | `w:sz=24` |
## 实测校验
用 pymupdf 读两版 PDF,逐位对比(原稿由 WPS 导出):
```
表格竖线 x (mm) 原稿 29.686 / 52.758 / 130.104 / 180.322
新版 29.687 / 52.758 / 130.104 / 180.321 Δ ≤ 0.001
表格横线 y (mm) 原稿 53.001 … 239.056(14 条)
新版 53.004 … 239.050 Δ ≤ 0.006
标题四字 x0 (pt) 原稿 222.00 / 270.00 / 318.00 / 366.00
新版 221.95 / 269.93 / 317.93 / 365.93 Δ ≤ 0.07
32 行文字水平中心 最大偏差 0.11pt
32 行文字距行顶 最大偏差 0.57pt(数字与中文各自字体度量差,见下)
字号 24.00 / 18.00 / 12.00 / 10.45 …………全部精确
```
> 纵向那 0.5pt 的来源:原稿序号列用 Times New Roman、正文用方正楷体,
> Word 让**两种字体各自按自身 ascent 落基线**,同一行里数字比中文高 0.48pt
> (原稿实测 232.25 vs 231.77)。新版用 Termes + OUC Kai 复刻了同样的
> 相对关系(232.32 vs 232.32 —— 差 0,因为 Termes 与 OUC Kai 的 ascent
> 恰好一致)。这是**字体度量差**,不是排版错误,且新版同一行内更整齐。
## 五个坑(改之前先看)
### 1. `\fontsize` 必须用 `bp`,不能用默认的 `pt`
Word/PDF 里的 "pt" 是 **PostScript point**(1/72 英寸),TeX 的默认 `pt` 是
**TeX point**(1/72.27 英寸),后者大出 0.36%。写 `\fontsize{24}{28.8}`,
PDF 里实测只有 **23.91**(= 24 × 72/72.27),与原稿的 24.00 对不上。
```latex
\fontsize{24bp}{28.8bp}\selectfont % 实测正好 24.000
```
本包所有照抄 Word 数值的字号、行距、间距一律写 `bp`。
### 2. xeCJK 会吞掉连续半角空格
标题原文是「归␣␣档␣␣目␣␣录」(字间各两个半角空格)。直接照抄进源码,
编译出来是紧贴的「归档目录」—— 空格全没了(实测 x0=216.09,且只有一个
span,而原稿是四个独立字、间隔恒 48pt)。
正解是不依赖空格策略,用 `\kern` 手动摆:
```latex
\newcommand{\gdgap}{\kern\gdtitlegap} % \gdtitlegap = 24bp = 1 个字宽
\gdtitle{归\gdgap 档\gdgap 目\gdgap 录}
```
### 3. 必须关掉 xeCJK 的全角标点压缩(`PunctStyle=plain`)
**这条最隐蔽。** 现象:凡含全角括号的行,整行右移 4.23pt,而字宽完全正确。
「试卷(项目设计报告)」原稿 x0=199.20,默认设置排出 **203.43**。
根因是 xeCJK 默认 `PunctStyle=quanjiao` 会对全角标点做字宽挤压:「(」「)」
的 advance 从 1.0em 压到 0.5em,省下的空间记在**行内盒子的起点**上,于是
整行墨迹相对盒子右移。两端对齐的正文里这叫"标点紧凑",但在**居中**的表格
单元格里就是整行偏移,且偏移量随括号个数变化(1 个 4.23pt、2 个 8.46pt)。
```latex
\xeCJKsetup{PunctStyle=plain}
```
Word 本来就不做这个挤压,关掉反而与原件一致。
### 4. `totalwidth` / 行高 / 位移都要比理论值多留一点
tabularray 的**计宽**与**画宽**不是一回事,三处都要实测标定:
- **列宽**:它把边框线宽算进列宽,故 `wd = gridCol − 2×colsep − 线宽`,
而不是"按竖线根数分摊"。按分摊算每列窄 0.154mm,整表窄 0.466mm。
- **表宽**:左竖线画在版心左边界**内侧**,整个 tblr 盒子比
`Σwd + 6×colsep + 4×线宽` 又多约 0.4945pt,不补足就报
`Overfull \hbox (0.49452pt too wide)`。
- **行高**:`row{..}={ht=..}` 是**内容区**高度,hline 线宽不含在内,
每行实际比 ht 高整整一个 `\gdrule`(0.5pt)。13 行累计多 6.5pt,
必须逐档减掉 0.1764mm。
### 5. 单元格里想"整体下移",只有一种写法有效
`\gdheadIII` 要让「标注」+ 小注两段整体下移 1.49pt,五种手段实测对比
(数值为距行顶距离,末项是两段间距):
| 手段 | 标注 | 小注 | 间距 | 结论 |
|---|---|---|---|---|
| 原样 | 25.43 | 46.53 | 21.09 | 偏低 1.49 |
| 尾部 `\vspace*{-2.98pt}` | 26.92 | 48.01 | 21.10 | ✅ 正确 |
| 顶部 `\vspace*{+2.98pt}` | 23.95 | 48.01 | 24.06 | 反向且拉大间距 |
| 顶部 `\rule{0pt}{26.5pt}` | 31.25 | 52.34 | 21.09 | 位移过大 |
| `\raisebox{-1.49pt}{\vbox{..}}` | 25.43 | 46.53 | 21.09 | 完全无效 |
原理:尾部间距 s 改变盒子总高 H(H' = H + s),m 居中后
内容顶端 = 行顶 + (行高 − H')/2。所以 **s 与位移是 2:1 关系**,
但实测灵敏度是 0.778 而非 0.5(hline 也参与高度分配),故最终标定值是
`\vspace*{-2.98pt}` 而不是 −1.49×2。
顺带一个反直觉的点:**顶部间距会被首行的 ascent 吃掉** —— 3.6pt 的
`\rule` 远小于 18pt 字的 ascent,写了等于没写;必须超过 ascent 才有反应,
但那时位移已经过量。所以"顶部加高"这条路走不通。
## 字体
全部来自仓库公共字体包 [`../fonts.tex`](../fonts.tex),来源与授权见
[`../fonts/README.md`](../fonts/README.md)。
原稿中文用「方正楷体_GB2312」(商业字体,不允许随仓库分发),现换成
**OUC Kai**(霞鹜文楷 GB2312 子集,SIL OFL 1.1)—— 同为楷体、同为
GB2312 字符集,字宽逐字相同(实测「考试签到表」= 60.00pt,
「试卷(项目设计报告)」= 120.00pt,与原稿全等)。西文/数字原用
Times New Roman,现用 **TeX Gyre Termes**(度量兼容替代)。
## 一个已知的"不改动"
原表 `tblGrid` 合计 8540 twips = **150.64mm**,而原版心 210 − 2×31.75
= **146.50mm** —— 原文档里这张表本来就在版心之外各溢出 2.07mm,靠
`jc=center` 居中掩盖,看起来正常。
本模板把版心直接设成表宽(150.81mm),表格居中与纸面绝对位置与原稿一致
(见上面的实测校验),但不再"溢出版心":**视觉上无差别,且不产生
Overfull 警告**。这是唯一的主动偏离,属修正而非改版。
+461
View File
@@ -0,0 +1,461 @@
%======================================================================
% oucgddir.sty — 信息科学与工程学部 试卷归档目录(理论课)版式包
%
% 依据:附件2:信息科学与工程学院归档目录(理论课).doc
% (SynologyDrive/授课/数字逻辑/2025/归档/)
% 原名与内文写的是「学院」,按现行建制改为「学部」,
% 模板标题相应为「信息科学与工程学部试卷归档目录」。
%
% 目标:版式与原 .doc 逐项对齐。所有尺寸都由 Word 内部数值换算:
% pt → mm : mm = pt / 72 * 25.4
% twips → mm : mm = twips / 1440 * 25.4
% w:sz : 半磅值,÷ 2 即 pt
%
% 用法见同目录 试卷归档目录.tex,说明见 README.md
%======================================================================
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{oucgddir}[2026/10/27 v1.0 OUC exam archive checklist]
\RequirePackage{geometry}
\RequirePackage{fontspec}
\RequirePackage{xeCJK}
\RequirePackage{tabularray}
%======================================================================
% 1. 页面与版心
%
% 原 .doc sectPr:
% pgSz w:w=11906 h:h=16838 → A4(210.01 × 297.00 mm)
% pgMar top/bottom = 1440 twips = 25.40 mm
% left/right = 1800 twips = 31.75 mm
% header 851 / footer 992 twips
%
% 但这张表本身【比版心宽】—— 这是原文档就存在的问题,不是这里引入的:
% 版心宽 = 210 − 2×31.75 = 146.50 mm
% 表宽 = tblGrid 合计 8540 twips = 150.64 mm
% ⇒ 表格比版心宽 4.14 mm,左右各溢出 2.07 mm。
% 原 Word 里 tblPr 是 jc=center + tblW=auto,所以表格是居中摆的,
% 左边界落在 29.60mm(= 31.75 − 2.07),实测 PDF 表格线 x 范围
% 29.60 ~ 180.41 mm,与此吻合。
%
% ⇒ 本包的处理:把 totalwidth 直接设成表宽 150.636mm,左右各留
% (210 − 150.636)/2 = 29.682 mm。这样
% · 表格与版心同宽,整表居中,编译不刷 Overfull \hbox
% · 表格线在纸面上的绝对位置与原 .doc 完全一致(误差 < 0.1mm)
% · 标题的居中基准也落在纸张中心,与原稿一致
% 即:不改动任何可见版式,只把"溢出版心"换成"版心就是表宽"。
%
% ⚠️⚠️【实测修正:totalwidth 要 150.8105mm,左边距 29.599mm】
%
% (a) 表宽的真实值不是 150.636mm。
% tabularray 把左竖线画在版心左边界【内侧】,线中心 = 边界 + 半线宽,
% 而右竖线外缘还要再占半个线宽,故整个 tblr 盒子的实宽比
% Σwd + 6×colsep + 4×线宽 多出约 0.4945pt。实测:
% Overfull \hbox (0.49452pt too wide)
% 须把 totalwidth 补足到 150.636 + 0.1745 = 150.8105 mm。
%
% (b) 左边距要 29.599mm 而非 29.682mm。
% 实测新版竖线 x 比原稿整体右偏 0.083mm(29.771 vs 29.686),
% 列宽与行距都已逐项精确,纯属整表平移,故左边距减 0.083mm。
% 此时 right 自动 = 210 − 29.599 − 150.8105 = 29.5905mm。
%
% 校正后实测:竖线 x = 29.686 / 52.758 / 130.104 / 180.322 mm,
% 与原稿 29.686 / 52.758 / 130.104 / 180.322 逐位相同。
%======================================================================
\geometry{
paperwidth = 210mm,
paperheight = 297mm,
left = 29.599mm, % 实测标定(见上)
totalwidth = 150.8105mm, % = 表真实宽(含 tabularray 取整余量)
top = 25.40mm,
bottom = 25.40mm,
headheight = 0pt,
headsep = 0pt,
footskip = 17.50mm,
}
\setlength{\parindent}{0pt}
\setlength{\parskip}{0pt}
\pagestyle{empty} % 原 .doc 无页眉页脚,故不排页码
%======================================================================
% 2. 字体与字号
%
% 原 .doc 全文只用「方正楷体_GB2312」一种中文字体,西文/数字用
% Times New Roman:
% 表外标题 楷体 24pt (w:sz=48)
% 表头三格 楷体 18pt 加粗 (w:sz=36 + w:b)
% 表头小字注释 楷体 10.45pt (w:szCs=21 未设 w:sz,Word 退回 10.5pt)
% 序号列 楷体 12pt 加粗 (w:sz=24 + w:b)
% 内容列 楷体 12pt (w:sz=24)
%
% ⚠️ 原字体是方正楷体 —— 商业字体,不允许随仓库分发。这里换成
% OUC Kai(霞鹜文楷 GB2312 子集,SIL OFL 1.1),字形风格一致
% (同为楷体、同为 GB2312 字符集),观感几乎无法区分。
% 字体全部来自仓库公共字体包 ../fonts.tex。
%
% ⚠️ 西文/数字:原文档用 Times New Roman。这里用 TeX Gyre Termes,
% 它是 Times 的度量兼容替代(字符宽度逐字相同),数字宽度零漂移。
%======================================================================
\input{../fonts.tex}
%----------------------------------------------------------------------
% ⚠️⚠️⚠️【最隐蔽的一条:必须关掉 xeCJK 的全角标点压缩】
%
% 现象:凡含全角括号「(」的行,整行右移 4.23pt,而字宽完全正确。
% 「试卷(项目设计报告)」原稿 x0=199.20,按默认设置排出 203.43。
%
% 根因:xeCJK 默认 PunctStyle=quanjiao,会对全角标点做**字宽挤压**:
% · 「(」「)」的 advance 从 1.0em 压到 0.5em
% · 挤压省下的空间被记在**行内盒子的起点**上(负的 \kern),
% 于是整行墨迹相对盒子右移
% · Word 不做这件事,全角括号就是整 1.0em
% 这在两端对齐的正文里看起来是"标点更紧凑",但在**居中**的表格
% 单元格里就会让整行偏移,且偏移量随括号个数变化(1 个括号 4.23pt,
% 2 个括号 8.46pt …),肉眼可见地不居中。
%
% 正解:\xeCJKsetup{PunctStyle=plain} —— 关闭挤压,全角标点按原字宽排。
% 代价:正文里中文标点的视觉密度略增(与 Word 完全一致,本就是目标)。
%
% ⚠️ 这条必须在 \begin{document} 之前设,且是**全局**的 ——
% 只对本模板生效,不影响仓库里其他模板(它们各自没这个包)。
%----------------------------------------------------------------------
\xeCJKsetup{PunctStyle=plain}
%----------------------------------------------------------------------
% ⚠️⚠️⚠️【最要命的一条,与 oucksfm.sty / ouclw.sty 同源】
% ctex 默认 \linespread 约 1.3,会把 \fontsize{12}{14.4} 的 14.4pt
% 行距放大成 18.7pt 以上,整张表会被撑高。
%
% \fontsize 的第二个参数【本来是】用来设 \baselineskip 的,但
% \selectfont 时会再乘一次 \linespread,所以必须先把 \linespread 归 1。
% 这一步不能省,也必须在 \AtBeginDocument 之后再设一次
% (ctex 在 begin document 时会重设)。
%----------------------------------------------------------------------
\newcommand{\gdbasefont}{%
\linespread{1}\relax
\fontsize{12bp}{14.4bp}\selectfont}
%----------------------------------------------------------------------
% ⚠️⚠️【字号必须用 bp,不能用默认的 pt】
%
% Word/PDF 里的 "pt" 是 PostScript point(1/72 英寸),而 TeX 的
% 默认 pt 是 TeX point(1/72.27 英寸),后者比前者大 0.36%。
% \fontsize{24}{28.8} 写出来,PDF 里实测只有 23.91(= 24 × 72/72.27),
% 与原稿的 24.00 对不上。
%
% 正解:显式写 bp 单位 —— \fontsize{24bp}{28.8bp},实测正好 24.000。
% 本包所有字号、行距、间距只要涉及"照抄 Word 数值"的,一律用 bp。
%----------------------------------------------------------------------
% 各档字号(行距取字号的 1.2 倍,与原 .doc 单倍行距一致)
\newcommand{\gdtitlefont}{\linespread{1}\relax\fontsize{24bp}{28.8bp}\selectfont}
\newcommand{\gdheadfont} {\linespread{1}\relax\fontsize{18bp}{21.6bp}\selectfont}
\newcommand{\gdnotefont} {\linespread{1}\relax\fontsize{10.45bp}{12.54bp}\selectfont}
\newcommand{\gdcellfont} {\linespread{1}\relax\fontsize{12bp}{14.4bp}\selectfont}
%----------------------------------------------------------------------
% ⚠️ xeCJK 陷阱:局部字体切换命令若紧邻 \par(或落在段落末尾),段末的
% 字体状态会"溢出"到后面段落。故局部切换一律用带 \normalfont 收尾的包装。
%----------------------------------------------------------------------
%======================================================================
% 3. 列的宽度模型
%
% 原 .doc tblGrid 三个网格列(twips → mm):
% c1 序号 = 1308 twips = 23.0717 mm
% c2 内容 = 4385 twips = 77.3465 mm
% c3 标注 = 2847 twips = 50.2179 mm
% ─────────────────────────────────────
% 合计 8540 twips = 150.6361 mm
%
% cellMar:left/right = 108 twips = 1.9050 mm,top/bottom = 0
% 边框 :w:sz = 4(单位 1/8 pt)⇒ 0.5 pt = 0.1764 mm
%
% tabularray 的 colsep 计在每列【左右两侧】,故 3 列共 6×1.905 = 11.430mm;
% 竖线 4 根(左边界 + 2 条内线 + 右边界)× 0.1764 = 0.7056mm。
% 要让 Σwd + 11.430 + 0.7056 = 150.636,需
% Σwd = 138.5005 mm
% 而 (gridCol − 2×1.905) 之和为 150.636 − 11.430 = 139.2061 mm,
% 两者差 0.7056 mm 正好是竖线总宽,故每列再减
% 竖线分摊 = 0.7056 / 3 = 0.2352 mm
%
% ⚠️ 上式是理论值。tabularray 的计宽与画宽之间有约 0.45 pt 的取整差,
% 实测需再微调(见 3.1 的实测标定值),否则报
% "Table width is too small, need 0.45pt more!" 外加一条 Overfull \hbox。
%
% ⚠️⚠️【实测标定:tabularray 把边框线宽算进列宽里】
% 实测每列"相邻竖线中心线间距" = wd + 2×colsep + \gdrule,
% 即比理论值 wd + 2×colsep 多出一个 0.1764mm 的线宽。
% 故正确的 wd 是
% wd = gridCol − 2×colsep − \gdrule
% 而不是 gridCol − 2×colsep − 竖线分摊。
% (按旧式"分摊"算出的 wd 偏小 0.154mm/列,整表窄 0.466mm,
% 实测原稿三列 23.072/77.346/50.218 而旧版 22.916/77.192/50.062。)
%======================================================================
\newcommand{\gdrule}{0.5pt} % 边框粗细(w:sz=4)
\newcommand{\gdcolsep}{1.905mm} % 单元格左右内边距(108 twips)
\newlength{\gdtblw}
\setlength{\gdtblw}{150.636mm} % 表宽(含 4 根竖线与 6 处内边距)
%----------------------------------------------------------------------
% 3.1 各列宽(= gridCol − 2×colsep − 竖线分摊)
% 与 gdtable 环境里 colspec 的 wd 必须逐字一致。
%----------------------------------------------------------------------
\newcommand{\gdwa}{19.0853mm} % c1 23.0717 − 3.8100 − 0.1764(线宽)
\newcommand{\gdwb}{73.3601mm} % c2 77.3465 − 3.8100 − 0.1764
\newcommand{\gdwc}{46.2315mm} % c3 50.2179 − 3.8100 − 0.1764
%----------------------------------------------------------------------
% 3.2 行高(扣掉边框线宽)
%
% ⚠️⚠️ tabularray 的 row{...}={ht=...} 是**内容区**高度,hline 的线宽
% 不包含在内 —— 实测每行都比 ht 高出整整一个 \gdrule(0.5pt):
% 原稿行距 39.00pt,按 ht=13.7583mm(=39.00pt) 排出来是 39.50pt
% 13 行累计多出 6.5pt,整表总高 533.88 vs 原稿 527.40
% ⇒ ht 需减去线宽 0.5pt = 0.1764mm:
% 表头 20.5493 − 0.1764 = 20.3729 mm
% 中间行 13.7583 − 0.1764 = 13.5819 mm
% 末 行 14.1640 − 0.1764 = 13.9876 mm
%----------------------------------------------------------------------
%======================================================================
% 4. 行高
%
% 原 .doc 每行都是 w:trHeight + w:hRule="exact"(固定行高,不是 atLeast):
% R1 表头 1165 twips = 20.5493 mm
% R2 ~ R13 780 twips = 13.7583 mm ← 12 行,逐行完全相同
% 最后一行 803 twips = 14.1640 mm ← 比其余 12 行高 0.406mm
% ────────────────────────────────────────
% 合计 20.5493 + 12×13.7583 + ... 见下
%
% ⚠️ 第 13 行(序号 12「试卷(项目设计报告)」)是 803 而非 780,
% 多出来的 23 twips 是 Word 里"字高 + 段前段后"凑出来的测量值,
% 照抄才能与原表逐行对齐。
%
% ⚠️ Word 的 exact 是"精确等于",内容超了会【被裁掉】。tabularray 的
% ht= 是最小行高(内容多则自动长高),语义更安全。本表各行内容都远
% 小于行高,两者结果相同,故直接写 ht=。
%======================================================================
%======================================================================
% 5. 表格环境
%
% ⚠️ 用 tblr 而非 longtblr:本表总高约 191mm,一页装得下(版心高
% 297 − 2×25.40 = 246.2 mm),不需要断页。
%
% ⚠️⚠️ colspec 与 row{} 必须字面写在这里,不能先存进宏再展开:
% tabularray 的列类型解析在宏展开之外进行,会报
% "Unexpandable command \xxx inside column type"。
% (所以 3.1 节那些 \gdwa… 只作文档用,不能拼进 colspec。)
%
% ⚠️ 选项里的宏名一律不带 @:tabularray 解析选项时 @ 不是字母。
%======================================================================
\newenvironment{gdtable}{%
\par\begingroup
\begin{tblr}[label=none]{
colspec={Q[c,m,wd=19.0853mm] Q[c,m,wd=73.3601mm] Q[c,m,wd=46.2315mm]},
colsep=1.905mm, rowsep=0pt, stretch=0,
hline{1-Z}={\gdrule}, vline{1-Z}={\gdrule},
row{1}={ht=20.3729mm},
row{2-Z}={ht=13.5819mm},
row{13}={ht=13.9876mm},
}%
}{%
\end{tblr}\par\endgroup}
%======================================================================
% 6. 单元格内容包装
%
% 本表全是单列格,tabularray 的 Q[c,m,wd=…] 已处理好居中与折行,
% 不需要 ouclw.sty 那种定宽 \parbox。这里只提供语义化的包装宏,
% 让 .tex 里不必反复写字体命令。
%======================================================================
% \gdno{数字} —— 序号列:楷体 12pt 加粗
\newcommand{\gdno}[1]{{\kaiti\bfseries\gdcellfont #1\normalfont}}
% \gditem{文字} —— 内容列:楷体 12pt
\newcommand{\gditem}[1]{{\kaiti\gdcellfont #1\normalfont}}
% 表头文字:楷体 18pt 加粗(只排字,不带任何垂直位移)
\newcommand{\gdheadraw}[1]{{\kaiti\bfseries\gdheadfont #1\normalfont}}
% 表头单元格(单段结构,用于「序号」「内容」两格)
%
% ⚠️ 尾部 \vspace*{1.58pt} 把这两个字【上移】0.99pt。
% 原稿基线距行顶 34.73pt,不处理时是 36.51pt(低了 1.78pt)。
%
% 方向推导:尾部间距 s 改变盒子总高 H(H' = H + s),m 居中后
% 内容顶端 = 行顶 + (行高 − H')/2。故 s > 0 ⇒ 顶端上移 s/2;
% s < 0 ⇒ 顶端下移 |s|/2。
% ⚠️ 实测 s 与位移不是严格 s/2 关系(因为行高是固定 ht,但单元格
% 还有 hline 参与分配),标定结果:
% s = 0 → 36.51(低 1.78)
% s = 3.56 → 33.74(高 0.99)
% 即 Δs=3.56 带来 Δ位移=2.77,灵敏度 0.778pt/pt。
% 要从 33.74 下移回 34.73,需 Δs = −1.99 × 0.778⁻¹… 反解得 1.58。
% 实测 s = 1.58 → 34.73,与原稿一致。
%
% 「标注」格是两段结构、自带自己的位移,故用 \gdheadraw 而非本宏。
\newcommand{\gdhead}[1]{\gdheadraw{#1}\par\vspace*{1.58pt}}
% 表头第三格的小字注释:楷体 10.45pt,不加粗
\newcommand{\gdnote}[1]{{\kaiti\gdnotefont #1\normalfont}}
%----------------------------------------------------------------------
% 表头第三格的两行结构
%
% 原 .doc 该格是【两个独立段落】:
% 段 1 「标注」 楷体 18pt 加粗,jc=center
% 段 2 「(确认存档后在此栏打√)」 楷体 10.45pt,不加粗,jc=center
%
% 实测两段的 y0 分别为 161.64 与 189.27 pt(相差 27.63pt),
% 说明它们是顺序排列的两行,不是同一行里的不同字号。
% 因此这里也用两个 \par 分开的段落,而不是塞进同一行。
%
% ⚠️ 第二段的字宽 379.08~500.65pt = 121.57pt = 42.89mm,
% 而该列内容可用宽只有 46.08mm(见 §3.1),余 3.19mm,
% 刚好排得下不折行 —— 与原稿一致。若换成别的字体/字号导致
% 折行,请把 §3.1 的 c3 略微加宽(同时减小 c2)。
%
% ⚠️⚠️【两段的垂直间距:原稿 21.12pt】
% 原稿两段基线相距 198.29 − 177.17 = 21.12pt。
% 而 18pt 楷体的行距(\baselineskip = 21.6pt)已把第二段的
% 起点推到了第一段基线 + 21.6pt 处,故两段之间的 \vspace 应当是
% **负值**才能得到 21.12pt:
%
% 间距 = 第一段行距 21.6 + \vspace → \vspace = −0.48pt
%
% 但实测 \vspace*{-0.48pt} 只排出 13.93pt,与 21.12 差 7.19pt。
% 原因是 \gdhead{...} 内部的 \gdheadfont 把 \baselineskip 重设成
% 21.6bp 之后,\par 结束时段落用的是**收尾组外**的 12bp/14.4bp,
% 故实际参与的是 14.4pt,不是 21.6pt:
% 间距 = 14.4 + \vspace → \vspace = +6.72pt
% 实测 6.72pt 正好排出 21.12pt。
%
% ⚠️ 三个 \par 段落会改变单元格盒子的总高,tabularray 的 m(垂直居中)
% 会据此重新计算基线位置 —— 故改这个值会连带影响「标注」二字的高度。
%
% ⚠️⚠️【整格下移 1.49pt:只能用"尾部负间距"】
% 两段间距调对(21.09 vs 原稿 21.12 ✓)后,整个格子比原稿高 1.49pt。
% 五种手段实测对比(距行顶距离,单位 pt,最后一项是两段间距):
% A 原样 25.43 / 46.53 / 21.09
% B 尾部 \vspace*{-2.98pt} 26.92 / 48.01 / 21.10 ← 正确
% C 顶部 \vspace*{+2.98pt} 23.95 / 48.01 / 24.06 ← 反向且拉大间距
% D 顶部 \rule{0pt}{26.5pt} 31.25 / 52.34 / 21.09 ← 位移过大
% E \raisebox{-1.49pt}{\vbox{...}} 25.43 / 46.53 / 21.09 ← 完全无效
%
% 为什么 B 有效:\vspace* 放在最后一段之后会缩短盒子的**总高**,
% m 居中按 (行高 − 总高)/2 定位,总高减 2.98 ⇒ 内容整体下移 1.49。
% 两者是 2 倍关系,别写成 1.49。
%
% 为什么 C/D 不行:顶部间距会被首行的 ascent 吃掉(3.6pt 远小于
% 18pt 字的 ascent),所以小 h 无效、大 h 又过量,没有可用区间。
% 为什么 E 不行:raisebox 在 tabularray 的单元格里被 m 居中的
% 重新计算抵消掉了。
%----------------------------------------------------------------------
\newcommand{\gdheadIII}{%
\gdheadraw{标注}\par
\vspace{6.72pt}%
\gdnote{(确认存档后在此栏打√)}\par
\vspace*{-2.98pt}}%
%======================================================================
% 7. 表外标题
%
% 原 .doc 第 2 段(idx 1):
% 楷体 24pt,jc 未设(左对齐),首行缩进 firstLine=2640 twips
% = 46.55 mm,且 firstLineChars=550(即 5.5 字宽)。
% 文字是「归 档 目 录」,字间各留两个半角空格。
%
% 实测 PDF:四个字 x0 = 222.00 / 270.00 / 318.00 / 366.00 pt,
% 相邻间距恒为 48.00 pt,每字宽 24.00 pt
% ⇒ 字间空隙 = 48.00 − 24.00 = 24.00 pt = 1 个字宽 = 2 个半角空格 ✓
%
% ⚠️⚠️【不能直接把「归 档 目 录」写进源码】
% xeCJK 默认开启 CJKecglue,且会把连续半角空格吞成一个,
% 写「归 档 目 录」编译出来是「归档目录」紧贴(空格全没了,
% 实测 x0=216.09 且只有一个 span)。
%
% 正解:用实测的间距自己摆 —— 每字之间插入 \gdtitlegap
% = 24.00pt = 8.467mm 的固定空白。这样得到的字符位置与原稿逐字相同,
% 且不依赖 xeCJK 的空格策略。
% 实现见下面的 \gdtitle:参数是【逗号分隔的字】,逐字排并插 gap。
%======================================================================
\newlength{\gdtitleindent}
%----------------------------------------------------------------------
% ⚠️⚠️【这个缩进不是 46.55mm,是 48.635mm】
%
% 原 .doc 的 firstLine = 2640 twips = 46.55mm,但它是从**版心左边界
% 31.75mm**(pgMar left=1800 twips)起算的:
% 31.75 + 46.55 = 78.30mm = 221.98pt ← 实测原稿标题 x0 = 222.00pt ✓
%
% 而本包把版心改成了表宽 150.636mm,左边界 29.682mm。若这里照抄
% 46.55mm,标题会落到 29.682 + 46.55 = 76.23mm = 216.02pt,
% 比原稿左移 5.91pt(2.08mm)—— 实测确实如此。
%
% ⇒ 补回这 2.151mm:48.701 = 46.55 + (31.75 − 29.599)
% 实测得到的标题 x0 = 222.00pt,与原稿逐字一致(四字间距 48.00pt)。
%----------------------------------------------------------------------
\setlength{\gdtitleindent}{48.701mm}
\newlength{\gdtitlegap}
\setlength{\gdtitlegap}{24bp} % 字间空隙 = 1 个字宽(实测 48−24)
% \gdgap —— 标题里的字间空隙,直接在 .tex 里逐字之间插入:
% \gdtitle{归\gdgap 档\gdgap 目\gdgap 录}
% 比"逗号分隔、宏里循环"直观得多,也不用 \makeatletter。
\newcommand{\gdgap}{\kern\gdtitlegap}
\newcommand{\gdtitle}[1]{%
\par\noindent
\hspace*{\gdtitleindent}%
{\kaiti\gdtitlefont #1\normalfont\par}}
%======================================================================
% 8. 标题与表格之间的空距
%
% 原 .doc 结构(body 子元素):
% idx 0 空段
% idx 1 标题「归 档 目 录」
% idx 2 空段
% idx 3 表格
% idx 4 空段
% idx 5 空段
%
% 实测:标题基线块 y0=97.78pt(34.50mm),表格顶线 y=150.00pt(52.92mm)。
% 标题字高 24pt、单倍行距 28.8pt = 10.16mm,故标题占 34.50 ~ 44.66mm;
% 标题段之后到表格顶线还差 52.92 − 44.66 = 8.26mm,
% 这一截由「空段(idx 2)」贡献。
%
% ⚠️⚠️【实测标定:9.943mm,不是 8.26mm】
% 理论值 8.26mm 是从"标题字块底 44.66mm"起算的,但 LaTeX 的
% \vspace 是从**基线 + 深度**之后起算,二者差一个 descent。
% 按 8.26mm 排出来表格顶线在 52.61mm,比原稿 53.00mm 高 0.39mm;
% 补足到 9.943mm 后实测 53.00mm,与原稿完全一致。
%======================================================================
\newlength{\gdheadskip}
\setlength{\gdheadskip}{9.943mm}
%======================================================================
% 9. 文档首部留白
%
% idx 0 是一个空段,占 1 行 = 28.8pt? 否 —— 它是 12pt 正文段落的空行,
% 单倍行距 = 14.4pt = 5.08mm。加上版心上边距 25.40mm,
% 标题块 y0 应为 25.40 + 5.08 = 30.48mm;
% 实测 34.50mm,差 4.02mm,是 Word 段前间距。故这里直接写到实测值。
%
% ⚠️⚠️【实测标定:2.7255mm,不是 4.02mm】
% 按 4.02mm 排出来,标题基线在 122.16pt,而原稿是 118.49pt,
% 低了 3.67pt = 1.2945mm。原因:4.02mm 是从"标题字块顶端"反推的,
% 而这里的 \vspace* 是从版心上边界往下量到**基线之上的高度**,
% 两者起算法不同,差了一个 ascent 的零头。
% ⇒ 4.02 − 1.2945 = 2.7255mm,实测标题基线 118.49pt,与原稿一致。
%
% 连带影响:表格整体也在同一基线之后,故此处一并归位;
% 表格顶线随之从 54.30mm 上移到 53.01mm(原稿 53.00mm)。
%======================================================================
\newlength{\gdtopskip}
\setlength{\gdtopskip}{2.7255mm}
\AtBeginDocument{\gdbasefont}
\endinput
Binary file not shown.
+61
View File
@@ -0,0 +1,61 @@
%======================================================================
% 中国海洋大学 信息科学与工程学部 试卷归档目录(理论课)
%
% 编译: xelatex 试卷归档目录.tex
%
% 这份表格用于装订试卷袋时逐项核对归档材料。共 12 项,装订顺序即
% 表格顺序,确认某项已存档后在最右「标注」栏内打 √。
%
% 版式来源:SynologyDrive/授课/数字逻辑/2025/归档/
% 附件2:信息科学与工程学院归档目录(理论课).doc
% (原文件名与内文写的是「学院」,现按现行建制改为「学部」)
%
% 与原 .doc 的差异(有意为之):
% · 单位名「学院」按现行建制改为「学部」,标题相应改为
% 「信息科学与工程学部试卷归档目录」
% · 原字体「方正楷体_GB2312」是商业字体,已换成 OUC Kai
% (霞鹜文楷,SIL OFL 1.1),同为楷体、同为 GB2312 字符集
% · 纸张、边距、表宽、列宽、行高、字号一律照原值,未做任何调整
% (详见 oucgddir.sty 的注释,每一项都附了换算过程)
%
% 与原 .doc 的一个【已知差异】(无法也无需还原):
% 原表的 tblGrid 合计 8540 twips = 150.64mm,比版心 146.50mm 宽
% 4.14mm,即原文档里这张表本来就在版心之外各溢出 2.07mm。
% Word 按 jc=center 居中摆放,所以看起来正常。
% 本模板把版心直接设成表宽,表格居中与纸面的绝对位置与原稿一致,
% 但不再"溢出版心"。视觉上无差别,且不会产生 Overfull 警告。
%======================================================================
\documentclass[UTF8,fontset=none]{ctexart}
\usepackage{oucgddir}
\begin{document}
\vspace*{\gdtopskip}
% ⚠️ 标题里的空格【不能】写成「归 档 目 录」—— xeCJK 会吞掉连续
% 半角空格,编译出来是紧贴的「归档目录」。必须用 \gdgap 手动插入
% 24bp(= 1 个字宽)的固定空隙,才能与原稿逐字对齐。
\gdtitle{归\gdgap 档\gdgap 目\gdgap 录}
\vspace{\gdheadskip}
\begin{gdtable}
%------------------- 表头 -------------------
\gdhead{序号} & \gdhead{内容} & \gdheadIII \\
%------------------- 12 项 -------------------
\gdno{1} & \gditem{考试签到表} & \\
\gdno{2} & \gditem{监考记录} & \\
\gdno{3} & \gditem{A、B试题(项目设计要求)} & \\
\gdno{4} & \gditem{A、B试题的参考答案(评分细则)} & \\
\gdno{5} & \gditem{试卷分析报告} & \\
\gdno{6} & \gditem{最终成绩构成说明} & \\
\gdno{7} & \gditem{最终成绩} & \\
\gdno{8} & \gditem{平时成绩} & \\
\gdno{9} & \gditem{期中考试成绩} & \\
\gdno{10} & \gditem{教学大纲} & \\
\gdno{11} & \gditem{教学日历} & \\
\gdno{12} & \gditem{试卷(项目设计报告)} & \\
\end{gdtable}
\par\null\par
\end{document}