Files
ouc_latex_template/劳务发放说明表/README.md
T
laoyang 1f807e9cce 所有模板目录改为中文名,并入幻灯片与科技报告两个仓库(#3)
目录改名(git mv 保留历史,包名不变):
  exam/   -> 试卷/
  form/   -> 年度考核登记表/
  form2/  -> 劳务发放说明表/
  course/ -> 课程执行大纲/

改名即可编译:实测 6 个模板在含中文的目录下 XeLaTeX 均零报错,
PDF 逐页文本与改名前的版本完全一致(0 页差异,仅元数据时间戳变化)。

并入两个此前独立维护的仓库:
  ouc-slide-latex-template  -> 幻灯片/
  ouc-report-latex-template -> 科技报告/
带入了 theme/ fonts/ logos/ figs/ cls/ input/ 与 fontawesome.pdf,
字体随模板附带(无须在系统安装)。中间文件一律不入库。

同步修正的文档:根 README 目录表改为中文名并说明统一维护;
四个子 README 的标题;ouclw.sty 注释里对 form/ 的交叉引用;
幻灯片与科技报告 README 里「从旧仓库 clone」「按年份切分支」等已失效的说明
(并入后只有 main 一个分支,各年份 TeX Live 通用)。

两个迁入模板的 PDF 保留源仓库原版(逐字节一致),未重新编译:
源 PDF 出自 TeX Live 2026,本机为 2022,重新编译会让结尾页装饰层定位
产生细微偏移,保留原版以保证样张与原来完全一致。
2026-10-26 18:31:04 +08:00

177 lines
7.5 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 | 同上,竖线计入行高 |
| 字体 | 宋体 | SimSun | 同一字体。缺字体时用 `fc-list` 找替代 |
| 标题 | 宋体 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。