重写全部 README,只保留使用说明

17 个 README 统一改成使用说明书,去掉来源、踩坑、需求过程等内容。

只保留:
- 怎么编译、跑几遍
- 文件结构
- 要改哪些参数(逐项列出宏名与含义)
- 用到的命令(表格)
- 版式参数

删除:
- 原文件来源、抽取过程
- 踩坑记录、最小复现、实测数据
- 用户需求、工单号、历史沿革
- 改造前后对比

行数 4185 → 2261。

全库 16/16 编译通过。
This commit is contained in:
2026-11-01 08:52:54 +08:00
parent a4bfcac82a
commit f87d763602
17 changed files with 1629 additions and 3334 deletions
+80 -151
View File
@@ -1,189 +1,118 @@
# 年度考核登记表 — 中国海洋大学 教职工年度考核登记表(LaTeX 版)
# 年度考核登记表
把学校下发的 Word 版《中国海洋大学教职工年度考核登记表》复刻为 LaTeX 模板,
版式与原 `.docx` 逐项对齐,**表格里不含任何真人信息**(姓名/职工号/出生年月/
单位/岗位全部是编的)。
> 样张填的是一份**完整的虚构考核表**:张远航(1985.03,信息科学与工程学部
> 计算机科学与技术学院,教授三级,中共党员),2025 年度,年度总结写了
> 思政 / 教学(176 学时)/ 科研(到账 320 万元)/ 人才培养四段。
> 之所以不写成满篇 `×`,是因为这张表**表格密、字数多**,光看叉号判断不出
> 行高会不会被内容撑开。虚构内容能直接看出「写这么多字正好排满 2 页」。
## 文件
| 文件 | 说明 |
| :-- | :-- |
| `年度考核登记表.tex` | 主文件。填表只改第 1 节(基本信息)与 `\khsummary`(年度总结) |
| `ouckhtb.sty` | 版式包。页面/字体/列宽/行高/全部尺寸都写在这里,附换算注释 |
中国海洋大学教职工年度考核登记表,A4 单页。
## 编译
```bash
cd 年度考核登记表
xelatex 年度考核登记表.tex
xelatex 年度考核登记表.tex # 跑两遍,第二遍取到正确页码
```
需要 **XeLaTeX**(用 fontspec + xeCJK),并安装:
`ctex`、`geometry`、`fontspec`、`xeCJK`、`tabularray`。
或仓库根:`bash build.sh 年度考核登记表`
字体不需要安装 —— 全部来自仓库公共字体包 `../fonts/`(由 `../fonts.tex` 加载),
详见 [`../fonts/README.md`](../fonts/README.md)。**不再依赖系统里的宋体/黑体/仿宋**。
## 文件
实测环境:TeX Live 2022 + `tabularray 2022A`。用 LuaLaTeX 理论上也行,但未验证。
| 文件 | 说明 |
|---|---|
| `年度考核登记表.tex` | 主文件,填内容改这里 |
| `ouckhtb.sty` | 版式包,一般不改 |
产出 2 页、A4、正反面打印正好。
## 填写参数
## 改内容
### 基本信息
全部在 `\begin{document}` 之前定义:
```latex
\khtbyear{2025} % 表头“2025 年度”那一行
\khtbyear{2025} % 考核年度,显示为表外标题的一部分
\newcommand{\khnum}{0000000} % 职工号
\newcommand{\khname}{{\fangsong 张远航}} % 姓名
\newcommand{\khsex}{{\fangsong 男}} % 性别
\newcommand{\khbirth}{{\fangsong 1985.03}} % 出生年月
\newcommand{\khdept}{{\fangsong 信息科学与工程学部}} % 单位(学部 / 学院)
\newcommand{\khsubdept}{{\fangsong 计算机科学与技术学院}} % 系(研究所、实验室、科室)
\newcommand{\khparty}{{\fangsong 中共党员}} % 政治面貌
\newcommand{\khtitle}{{\fangsong 教授}} % 现专业技术职务
\newcommand{\khpost}{{\fangsong 教授三级}} % 所聘岗位
\newcommand{\khnum} {0000000} % 职工号
\newcommand{\khname} {{\fangsong 张远航}} % 姓名
\newcommand{\khsex} {{\fangsong 男}} % 性别
\newcommand{\khbirth} {{\fangsong 1985.03}} % 出生年月
\newcommand{\khdept} {{\fangsong 信息科学与工程学部}} % 单位
\newcommand{\khsubdept} {{\fangsong 计算机科学与技术学院}} % 系/研究所/科室
\newcommand{\khparty} {{\fangsong 中共党员}} % 政治面貌
\newcommand{\khtitle} {{\fangsong 教授}} % 现专业技术职务
\newcommand{\khpost} {{\fangsong 教授三级}} % 所聘岗位
```
> 上列值是**样张实际用的虚构内容**。职工号 `0000000` 故意留着没编 ——
> 职工号位数各校各单位不等,编一个反而会误导「照这个位数填」。
>
> ⚠️ 「出生年月」的**标签**不是写在 `\khbirth` 里,而是单独的
> `\khbirthlabel`(默认 `出生\par 年月`,折两行)。原因见下文第 0 条:
> 那一格只有 15.31mm,放不下 4 个 14pt 的字(要 19.68mm)。
> 想让标签恢复成一行「出生年月」,值就会重新被挤掉。
| 参数 | 说明 |
|---|---|
| `\khtbyear{年}` | 考核年度 |
| `\khnum` | 职工号 |
| `\khname` | 姓名 |
| `\khsex` | 性别 |
| `\khbirth` | 出生年月 |
| `\khdept` | 单位(学部/学院) |
| `\khsubdept` | 系、研究所、实验室、科室 |
| `\khparty` | 政治面貌 |
| `\khtitle` | 现专业技术职务 |
| `\khpost` | 所聘岗位 |
> **`{\fangsong ...}` 不能去掉。** 占位符 `×` 是 U+00D7,xeCJK 默认按 Unicode
> 区段把它判成**西文**,交给 fontspec 的西文字体(Termes/Times),而那儿的
> `×` 宽度与汉字不一致,几个就能撑破整列。
>
> **更好的做法**:`../fonts.tex` 里已经全局加了
> `\xeCJKDeclareCharClass{CJK}{"00D7}`,把 `×` 归入 CJK 字符类 ——
> 于是它自动按汉字全角宽度排,**不必再包 `\fangsong` 也不会撑破**。
> 这是本次字体改造顺带修掉的老 bug(原注释的修法从未真正生效过)。
参数值里的 `{\fangsong ...}` 是指定字体,可去掉换成其他字族。
### 年度总结
## 年度总结正文
```latex
\newcommand{\khsummary}{%
第一段……\par
第二段……\par
第三段……}
第一段内容。\par
第二段内容。\par
第三段内容。}
```
段间用 `\par`(不要用空行 —— 空行在 `\newcommand` 参数里会被当成分段但不易数)。
首行自动缩进 2 字,末行自动带「本人签名 / 年 月 日」,都写在 `ouckhtb.sty` 里。
多段之间用 `\par` 分隔,不要留空行。
## 版式数据来源
## 表格结构
所有尺寸都从 `.docx` 内部的 OOXML 数值换算,不使用目测:
| 区段 | 内容 |
|---|---|
| 表头 | 职工号、姓名、性别、出生年月 |
| 基本信息 | 单位、系、政治面貌、职务、岗位 |
| 年度总结 | `\khsummary` 的长文本格,竖排标题 |
| 考核结果 | 三级选择与签字 |
| 签名栏 | 本人签字、单位意见、学校意见 |
```
twips → mm : mm = twips / 1440 × 25.4
twips → pt : pt = twips / 20 (1 pt = 1/72 in)
w:sz : 半磅值,÷ 2 即 pt
## 改表格内文字
正文在表格环境内,每行用 `&` 分列。合并格里的文字**必须用 `\khtbfit`
包起来**,指定跨度宽度:
```latex
\SetCell[c=2]{c} \khtbfit{\khtbspanA}{单\hspace{1em}位} & &
\SetCell[c=3]{c} \khtbfit{\khtbspanB}{\khdept} & & &
```
| 项 | docx 值 | LaTeX 值 |
| :-- | :-- | :-- |
| 纸张 | 11907 × 16840 twips | A4(210 × 297 mm) |
| 表宽 `tblW` | 8976 twips | 158.33 mm(11 列 + 边框) |
| 11 个 `gridCol` | 1087 283 1221 1047 284 1105 952 600 870 80 1447 | 见 `ouckhtb.sty` 第 3.1 节 |
| 正文字号 | `w:sz=28` | 仿宋 14 pt / 行距 15.6 pt |
| 大标题 | `w:sz=44`,`w:spacing=-14` | 黑体 22 pt / 字距 −0.7 pt |
| 行高 `trHeight` | 412 460 939 1261 1252 1009 556 1258 1258 | 7.27 / 8.11 / 16.56 / 22.24 / 22.08 / 17.80 / 9.81 / 22.19 / 22.19 mm |
不包的话文字不会折行,会把表格撑出版心。
### 页边距为什么不照抄 docx
### 跨度常量
docx 是左右各 30 mm 版心(150 mm),但表宽 158.33 mm 比它还宽 8.33 mm,
Word 是靠 `tblPr/jc=center` 把这张表“压”进页边距里的。
| 常量 | 对应列 |
|---|---|
| `\khtbspanA` … `\khtbspanH` | 各格的跨度宽度 |
| `\khtbwa` … `\khtbwk` | 各列宽度 |
本模板把页边距改成 `(210 − 158.33)/2 = 25.835 mm`,使 `\textwidth` 恰好等于表宽:
### 其他常用命令
- 表格天然居中,不需要 `\leftskip` / `\centerline` 之类的偏移;
- **表格在纸面上的绝对位置与 Word 完全一致**(左右各 25.835 mm);
- 编译时不会刷 `Overfull \hbox`。
| 命令 | 用途 |
|---|---|
| `\khtbtitle` | 印表外标题(含年度) |
| `\khtbcell{文字}` | 定宽盒子 |
| `\khtbvert{标题}` | 竖排格标题(用于年度总结格) |
| `\khtbunderline{n}` | 下划线空行 |
| `\khtbchoices` | 考核结果的三级选项 |
| `\khtbseal` | 盖章位 |
| `\khtbsign` | 签字位 |
| `\khtbsummarysign` | 年度总结格下方的签字 |
| `\khtbstack{...}` | 多行堆叠 |
| `\khtbxi` | 系/研究所一栏的值 |
表外文字(标题、脚注)仍是水平居中,视觉上与 30 mm 版心没有差别。
## 版式
## 排版时的坑(sty 里都有详细注释)
0. 🔴 **表头 `cell{r}{c}={c=n}` 会静默丢内容 —— 已全部改成行内 `\SetCell`。**
这是本模板最难查的一个 bug:某个格子的值**整格不显示**,日志零 error 零
warning,光看日志和 PDF 页码完全发现不了。
- 现象:「出生年月」的值一直是空白。用 `××××.××` 占位时也是空白,
所以原版一直没人发现;换成真实内容才暴露。
- 根因:`cell{r}{c}` 里那个 `c` 是**数据行的单元序号**,不是视觉列号。
表头那三处 `c=2` 加起来要求该行吃掉 15 个视觉列,而表只有 11 列,
超出部分被静默丢弃 —— 丢的正好是最后一个值。
- 迷惑点:同一行写 12 格 → 丢值;写 10 格 / 9 格 → **反而显示**
(空缺给了它余量)。所以「格子数对不对」在这里完全不能当判断依据。
- 正解:表头不写 `cell{}`,合并直接标在被合并的那格上:
`\SetCell[c=2]{c} 职工号 & & 0000000 & ...`,每行照常写满 11 格。
- 附带修的:这个表 R0 行本来就装不下 —— 前六个字段已占 115.76mm,
剩 42.20mm 要装「出生年月」标签(19.68mm)+ 值(17.22mm),
但列宽被 `c9=15.31 / c10=1.38 / c11=25.51` 切死,标签占不住 c9
只能整体右移,值就被挤出去。处理是把标签折成两行「出生 / 年月」
(每行 9.84mm 放得下),值回到 c10-c11。**列宽一个都没改。**
1. **合并单元格不折行。** 合并格的单元类型 `{c}` 是 LR 模式,
格子里的文字比所跨各列合计更宽时,它**不折行,而是把列撑宽、整表超出版心**。
实测「系(研究所、实验室、科室)」把表从 448 pt 撑到 559 pt。
→ 所以合并格里的文字一律包 `\khtbfit{跨度宽宏}{文字}`。
单列的 `Q[c,m,wd=…]` 没有这个问题(超了只是溢出,列宽不变)。
2. **合并格里的 `\hsize` 没被重设。** span=10 的格子里 `\hsize` 仍是整页版心宽,
长文本会按 450 pt 折行、冲出格子。→ 长内容必须用定宽 `\parbox`(`\khtbcell`)。
3. **跨度声明写法:`cell{r}{c}={c=n}{c}` 与行内 `\SetCell[c=n]{c}` 都要用
`{c=n}{c}` 这一种。** `={c=n}`、`={n}{c}`、`={span=n}{c}` 都不认,最后那个
会报 `The key 'tblr-cell-span/span' is unknown`。
⚠️ 但如第 0 条所述,**跨列请优先用行内 `\SetCell`**,表头 `cell{}` 有丢内容的风险。
4. **`colspec` / `row{}` 里不能放宏。** tabularray 在宏展开之外解析列类型,
会报 `Unexpandable command … inside column type`。所以列宽只能字面写死。
另外两个容易忘的:
- `longtblr` 默认会把各列按 `\textwidth` 等比拉伸(`tblr` 不会),必须写 `stretch=0`;
- `longtblr` 会在续页处印「表 0: (Continued)」,必须用 `\DefTblrTemplate` 把
`caption` / `capcont` / `conthead-text` / `contfoot-text` **四个模板全清**。
## 与原 docx 的已知差异
| 位置 | docx | 本模板 | 说明 |
| :-- | :-- | :-- | :-- |
| 表头「×××× 年度」 | `firstLine` 缩进 2 字、未设居中 | 居中 | 更像原排版疏漏,按意图改居中。想还原就把 `\khtbtitle` 里的 `\centering` 换成 `\hspace*{2\ccwd}` |
| 「师德考核结果」首列 | `师师德考核结果` | `师德考核结果` | docx 原文首字重复(WPS 竖排遗留),已按正常写法更正 |
| 「单位年度考核建议档次」首列 | `单单位年度考核建议档次` | `单位年度考核建议档次` | 同上 |
| 单元格内边距 | 左右各 108 twips(1.905 mm) | 0 | c10 只有 1.41 mm,比两倍内边距还窄,统一内边距会算出负宽。代价是文字可贴竖线,但全部单元格本就水平居中,观感一致 |
| 未勾选框 | Wingdings `¨`(char 0x00A8) | U+25A1 `□` | Wingdings 在 Linux/macOS 上不可靠。仓库里的仿宋、黑体、宋体都含 `□`;且 `../fonts.tex` 已把 U+25A1 归入 CJK 类,不会再落到不含该字的西文字体上 |
| 电子签名图片 | 内嵌两张手写签名 JPEG | 无 | 模板不含真人信息 |
## 校验方法(想改版式时照这个验)
不要靠肉眼看 PDF。用矢量坐标对:
```bash
xelatex 年度考核登记表.tex
pdftocairo -svg 年度考核登记表.pdf pg.svg # 转成 SVG 取精确线条坐标
pdftotext -bbox 年度考核登记表.pdf - # 取每个字的 xMin/yMin/xMax/yMax
```
A4,单页
表格行高按原表设定,年度总结格为高行
```
正确结果应当满足:
## 注意
- 表格左边界 73.14 pt、右边界 520.91 pt(宽度 447.8 pt ≈ 157.96 mm);
- 表格所有横线都是 **10 段**(8 个网格列位置被合并掉,只剩 10 段可见);
- 页数为 2;
- `grep "Overfull\|too small" 年度考核登记表.log` 无输出。
当前状态:**零 Overfull、零 Underfull、2 页、表宽 157.96 mm**(目标 158.33 mm,
差 0.23%,为消除 0.45 pt 的 `Overfull` 累积误差而取整所致,肉眼不可辨)。
示例内容为虚构数据,使用时全部替换。签字、日期栏留空手填。