Files
ouc_latex_template/劳务发放说明表/README.md
T
laoyang 8aa979739a 字体统一:建公共字体目录,全部改用开源可商用字体 (#6)
七个模板原先分两套做法:幻灯片/fonts(49MB 鸿蒙 18 个字重)与
科技报告/font(92MB,含 5 款方正商业字体),其余模板直接调系统
SimSun/SimHei/KaiTi/FangSong/Times New Roman。换机器就编不出来,
方正系列也不允许随仓库分发。

统一到仓库根的 fonts/ + fonts.tex:
- OUC Serif(思源宋体 SC 子集)   —— 宋体
- OUC Sans(思源黑体 SC 子集)    —— 黑体
- OUC Kai(霞鹜文楷子集)          —— 楷体
- Zhuque Fangsong(朱雀仿宋)      —— 仿宋
- TeX Gyre Termes                  —— 西文 Times 等价(度量逐字相同)
- HarmonyOS Sans                   —— 幻灯片/科技报告原有字体

fonts.tex 是唯一允许声明字体的地方,7 个模板全部 \input 它。
字体体积 141MB -> 49MB(去掉重复),全库共用一套最小集合。

几处踩过的坑(均已写进源码注释):
- \newCJKfontfamily 与 ctex 默认 fontset 冲突会中断编译,改用
  \setCJKfamilyfont + \def
- \newfontfamily 缺粗体档会让 \bfseries 静默失效,四档必须全给
- UprightFont= 与主参数不能同时给,否则文件名被拼两次
- Path= 相对编译时工作目录,不是相对 .sty
- ×/□/○ 等符号按 Unicode 区段被判成西文,需 \xeCJKDeclareCharClass
- 中文斜体的 ItalicFont 与主字体不在同一目录,须在 ItalicFeatures
  里单独写 Path/Extension(否则报 OUCKai-Regular cannot be found)

顺带:
- 科技报告 report.tex 的字体演示正文改为新字体名(原文写着方正系列)
- 试卷归档封面新模板并入本库
- 科技报告 shell 命令框底色改海大蓝(#5 遗留)

验证(7 个模板 8 个 PDF 全量重编 + 逐行 A/B 对照):
- 错误 0,缺字 0
- 幻灯片 362 行逐行完全一致,零漂移
- 年度考核登记表 / 劳务发放说明表 / 试卷题型示例 / 参考答案 文本完全一致
- 课程执行大纲 仅 2 处断字连字符差异(throughout、processing),
  1 条 6.39pt Overfull 已论证不可见(距纸张右边缘仍有 20.7mm)
- 科技报告 内嵌字体方正归零,只剩 OUC Serif/Sans/Kai + Zhuque
- 全库正文 857 个非 ASCII 字符,四款中文字体(含粗体)覆盖 100%
2026-10-27 00:43:14 +08:00

177 lines
7.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 劳务发放说明表 — 中国海洋大学 劳务发放说明表(LaTeX 版)
把实验室用的《劳务发放说明表》Word 版复刻为 LaTeX 模板。版式与原 `.docx`
逐项对齐,**不含任何真人信息**:姓名、人数、项目名称、单位名称一律 `×` 占位。
## 文件
| 文件 | 说明 |
| :-- | :-- |
| `劳务发放说明表.tex` | 主文件。填表只改第 1 节(4 个变量) |
| `ouclw.sty` | 版式包。页面/字体/列宽/行高/全部尺寸写在这里,附换算注释 |
## 编译
```bash
xelatex 劳务发放说明表.tex
```
单页,跑一遍即可(无交叉引用)。
需要 **XeLaTeX**,并安装 `ctex`、`geometry`、`fontspec`、`xeCJK`、`tabularray`。
实测环境:TeX Live 2022 + `tabularray 2022A`。
## 改内容
```latex
\newcommand{\lwunit}{{\songti ××××××××}} % 用工单位(学部 / 学院)
\newcommand{\lwreason}{{\songti ××××}} % 用工事由
\newcommand{\lwnote}{} % 备注(可留空)
\newcommand{\lwwork}{%
聘请{\songti ×××}等{\songti ×}位研究生参与《{\songti ×××}》项目的研究工作。}
```
### 关于 `\lwwork` 的句式
原文是「聘请秦依康等 2 位研究生参与《观测数据驱动的渤海生态系统健康评估
关键技术研发》项目的研究工作。」——真人姓名、人数、真实项目名已替换为
`×××` / `×`,**句式一字未动**。填表时把三处 `×` 换成实际内容即可:
| 占位 | 换成 |
| :-- | :-- |
| 第一个 `×××` | 第一位研究生的姓名("等"字后面若只有一人,可删"等×位") |
| `×`(位) | 研究生人数 |
| 《`×××`》 | 项目全称 |
## 版式数据来源
全部尺寸从原 `.docx` 的 OOXML 里量出来,换算关系:
- 长度:`mm = twips ÷ 1440 × 25.4`,`pt = twips ÷ 20`
- 字号:`w:sz` 是半磅值,`sz=28` ⇒ 14 pt
- 行距:`docGrid linePitch=312` twips ⇒ 15.6 pt
| 项目 | docx 原值 | 换算 |
| :-- | :-- | :-- |
| 纸张 | `pgSz 11906×16838` | A4 210×297 mm |
| 页边距(上下) | `pgMar top/bottom 1361` | 24.01 mm |
| 页边距(左右) | `pgMar left/right 1797` | 31.70 mm |
| 表宽 | `tblW 8522` | 150.32 mm |
| 列宽 c1..c4 | `1384, 1418, 2883, 2837` | 24.41 / 25.01 / 50.85 / 50.04 mm |
| 单元格内边距(左右) | `tblCellMar 108` | 1.905 mm |
| 边框 | `tblBorders sz=4` | 0.5 pt |
| 字号 | `w:sz 28` | 14 pt,宋体 |
| 行距 | `linePitch 312` | 15.6 pt |
各行行高由**段落数**决定(原表没有 `trHeight`),每段一个行距 15.6 pt:
| 行 | 段数 | 高度 |
| :-- | :-- | :-- |
| R0 用工单位 | 2(`用工单位` / `(公章)`) | 31.2 pt = 11.01 mm |
| R1 用工事由 | 1 | 15.6 pt = 5.50 mm |
| R2 具体工作 | 9(长句 + 8 空段) | 140.4 pt = 49.53 mm |
| R3 三方签字 | 4(标签 + 2 空段 + 日期) | 62.4 pt = 22.01 mm |
| R4 备注 | 2 | 31.2 pt = 11.01 mm |
| 合计 | | 280.8 pt = 99.06 mm |
### 为什么左右页边距不对称
原表宽 150.32 mm,比 docx 版心(146.68 mm)宽 3.71 mm,而 `tblPr` 里**没有
`jc`、`tblInd` 又是 0** —— Word 按左对齐处理:表从左边距 31.70 mm 起排,
右端溢进右侧页边距 3.71 mm。
所以本模板照实复现这个不对称:`left = 31.70mm`、`totalwidth = 150.32mm`,
右边界自然落到 `210 − 31.70 − 150.32 = 27.98 mm`。**不要**改成左右等边距
(那样表会整体左移 1.86 mm,与 Word 里看到的位置不符)。
## 四个必须知道的坑
### 1. ctex 的 `\linespread ≈ 1.3` 会吃掉你设的行距
```latex
\fontsize{14}{15.6}\selectfont % \baselineskip = 20.28pt ✗
\linespread{1}\relax\fontsize{14}{15.6}\selectfont % = 15.60pt ✓
```
`\fontsize` 第二个参数本该直接设定 `\baselineskip`,但 `\selectfont` 时会
**再乘一次 `\linespread`**。ctex 默认 `\linespread ≈ 1.3`,于是 15.6 pt 被放大
成 20.28 pt,五行表从 99 mm 涨到 129 mm,`ht=` 也压不住(内容本身就那么高,
tabularray 只能被动撑开)。
本包的对策是 `\lwbodyfont`:
```latex
\newcommand{\lwbodyfont}{\linespread{1}\relax\fontsize{14}{15.6}\selectfont}
\AtBeginDocument{\lwbodyfont}
```
`\AtBeginDocument` 那一次不能省——ctex 在 begin document 时会重设 `\linespread`。
### 2. 合并格 `{c}` 是不折行的 LR 模式
`cell{r}{c}={c=n}{c}` 的 `{c}` 是 **LR 模式**,不是段落模式:
- 格内文字比所跨各列合计更宽时,它**不折行**,而是把列撑宽、整表超出版心;
- 合并格里的 `\hsize` **没有**被重设成该跨度宽度,仍是外层版心宽,
长文本会按版心折行、冲出格子。
⇒ 合并格里的文字一律包定宽 `\parbox`,本表提供 `\lwcell` / `\lwcellv` /
`\lwstack` / `\lwsign` 四个入口,`.tex` 里只要有内容就用它们,别裸写。
### 3. 合并格的“内容可用宽”要补回 `2·colsep·(n−1)`
单列的内容宽 = `wd`(左右两半 `colsep` 已被 colspec 扣掉);
但跨 n 列合并后,**n 列之间的 (n−1) 组内边距会被回收进内容宽**:
```
内容可用宽 = Σ 所跨各列 wd + 2 · colsep · (n − 1)
```
漏算的后果很隐蔽:`\parbox` 比真实格宽窄,短文本看不出问题,长文本会
**提前折行**。本表「批准单位负责人签字」共 9 字 × 14 pt = 44.45 mm,
而 c1+c2 只有 41.37 mm,就曾被折成「批准单位负责人签」+「字」两行,
docx 里明明是一行。正确值是 `41.3653 + 2×1.905 = 45.1753mm`。
### 4. `\parbox[t]` 会让行高超目标
tabularray 给每个单元格垫了 strut,`[t]` 生成的盒子顶部与 strut 顶部相加,
实测每行白白多出 **3.6 pt**(R0 从 31.67 → 35.26)。
原表 R0C1 / R2C1 之所以“贴顶”,不是靠 `vAlign=top`(它们其实没写 `vAlign`),
而是靠**段落数把行高填满**(2 段 = 31.2 pt、9 段 = 140.4 pt,正好等于行高)。
内容高度已等于行高时,`[c]` 居中的结果就等同于贴顶。
⇒ `.tex` 里用 `\lwcellv{内容\lwblank{n}}` 补足段落数,`\parbox` 保持 `[c]`。
## 与 docx 的已知差异
| 项 | docx | 本模板 | 说明 |
| :-- | :-- | :-- | :-- |
| 表宽 | 150.319 mm | 150.137 mm | 差 0.18 mm。tabularray 计宽按 n−1 根竖线、画宽按 n 根,系统性差 0.5 pt,为消除 Overfull 微调了列宽 |
| 行高 | 11.01 / 5.50 / 49.53 / 22.01 / 11.01 mm | 每行 +0.15 mm | 同上,竖线计入行高 |
| 字体 | 宋体 | OUC Serif(思源宋体子集) | 原用系统 SimSun。现改为仓库公共字体包 `../fonts/`,换机器/换系统都能编,且允许分发 |
| 标题 | 宋体 14 pt **加粗** | 同 | 字号与正文相同,只靠加粗区分 |
## 校验方法
不用肉眼看 PDF,直接量矢量:
```bash
pdftocairo -svg 劳务发放说明表.pdf out.svg # 取线条精确坐标
pdftotext -bbox 劳务发放说明表.pdf out.xml # 取每个字块的坐标
```
SVG 里解析 `<path d="M x y L x y" transform="matrix(...)"/>`,按
「`|Δy|<0.9` 且 `|Δx|>10` = 横线」「`|Δx|<0.9` 且 `|Δy|>2` = 竖线」分类去重,
即可得到每条线的精确端点。本模板的实测结果:
```
表宽 150.137 mm (目标 150.319,差 −0.18)
表左 31.662 mm (目标 31.700,差 −0.04)
表右 181.799 mm (目标 182.019,差 −0.22)
R0 11.172 / R1 5.668 / R2 49.646 / R3 22.159 / R4 11.172 mm 全部达标
```
三个签字格的标签基线完全重合(`rel-top 1.06 pt`),日期行也完全重合
(`rel-top 47.69 pt`)——这一条是特意做的:合并格与普通列的垂直居中算法
不同,若不统一包 `\parbox`,第一格会比另两格低 1.55 pt。