重写全部 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
+61 -148
View File
@@ -1,183 +1,96 @@
# 劳务发放说明表 — 中国海洋大学 劳务发放说明表(LaTeX 版)
# 劳务发放说明表
把实验室用的《劳务发放说明表》Word 版复刻为 LaTeX 模板。版式与原 `.docx`
逐项对齐,**不含任何真人信息**:姓名、人数、项目名称、单位名称全部是编的。
## 文件
| 文件 | 说明 |
| :-- | :-- |
| `劳务发放说明表.tex` | 主文件。填表只改第 1 节(4 个变量) |
| `ouclw.sty` | 版式包。页面/字体/列宽/行高/全部尺寸写在这里,附换算注释 |
中国海洋大学劳务费发放说明表,A4 单页。
## 编译
```bash
cd 劳务发放说明表
xelatex 劳务发放说明表.tex
```
单页,跑一遍即可(无交叉引用)。
或仓库根:`bash build.sh 劳务发放说明表`
需要 **XeLaTeX**,并安装 `ctex`、`geometry`、`fontspec`、`xeCJK`、`tabularray`。
实测环境:TeX Live 2022 + `tabularray 2022A`。
## 文件
## 改内容
| 文件 | 说明 |
|---|---|
| `劳务发放说明表.tex` | 主文件,填内容改这里 |
| `ouclw.sty` | 版式包,一般不改 |
## 填写参数
全部在 `\begin{document}` 之前定义:
```latex
\newcommand{\lwunit}{{\songti 信息科学与工程学部}} % 用工单位(学部 / 学院)
\newcommand{\lwreason}{{\songti 科研项目数据整理}} % 用工事由
\newcommand{\lwnote}{} % 备注(可留空)
\newcommand{\lwwork}{%
聘请{\songti 李承宇}等{\songti 2}位研究生参与《{\songti 近岸海域生态健康
多源数据融合与智能评估技术}》项目的研究工作。}
\newcommand{\lwunit} {{\songti 信息科学与工程学部}} % 用工单位
\newcommand{\lwreason}{{\songti 科研项目数据整理}} % 用工事由
\newcommand{\lwnote} {} % 备注,可留空
\newcommand{\lwwork}{% % 用工说明正文
聘请{\songti 李承宇}等{\songti 2}位研究生参与……}
```
上列值是**样张实际用的虚构内容**(人名校验过:`李承宇` 不对应任何真实人员)。
| 参数 | 说明 |
|---|---|
| `\lwunit` | 用工单位(学部/学院) |
| `\lwreason` | 用工事由 |
| `\lwnote` | 备注,可留空 |
| `\lwwork` | 用工说明正文,即表格中「工作内容」一栏 |
### 关于 `\lwwork` 的句式
参数值里用 `{\songti ...}` 包裹是为了指定字体,可去掉。
原文是一句「聘请某研究生等 N 位参与某项目研究工作」的表述 ——
真人姓名、人数、真实项目名均未保留,**句式一字未动**。
填表时把这三处换成实际内容即可:
## 表格结构
| 样张值 | 含义 | 换成 |
| :-- | :-- | :-- |
| `李承宇` | 第一位研究生的姓名 | 真实姓名("等"字后面若只有一人,可删"等 N 位") |
| `2`(位) | 研究生人数 | 实际人数 |
| 《`近岸海域…技术`》 | 项目全称 | 真实项目名 |
| 行 | 内容 |
|---|---|
| R0 | 用工单位(盖章) + 单位名称 |
| R1–R3 | 用工事由 + 工作内容 + 备注 |
| R4 | 三处签字:批准单位负责人 / 用工单位负责人 / 经办人 |
> 不是满篇 `×` 的原因:这张表**正文只有一句话**,全打叉的话整页看着像没填完,
> 也判断不出这句话在该行里排几行。填一句完整的话才知道行高要不要调。
## 改表格内文字
## 版式数据来源
正文在 `\begin{lwtable}` 与 `\end{lwtable}` 之间。每行写满 4 个格子(3 个 `&`)
加结尾 `\\`。跨度已固定在 `ouclw.sty` 里,不用管。
全部尺寸从原 `.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` 会吃掉你设的行距
合并格里的文字**必须用 `\lwfit` 或 `\lwcell` 等定宽盒子包起来**:
```latex
\fontsize{14}{15.6}\selectfont % \baselineskip = 20.28pt ✗
\linespread{1}\relax\fontsize{14}{15.6}\selectfont % = 15.60pt ✓
& \lwcellv{\lwunit\lwblank{1}}
& \lwcellv{\lwreason}
& \lwwork\lwblank{8}
```
`\fontsize` 第二个参数本该直接设定 `\baselineskip`,但 `\selectfont` 时会
**再乘一次 `\linespread`**。ctex 默认 `\linespread ≈ 1.3`,于是 15.6 pt 被放大
成 20.28 pt,五行表从 99 mm 涨到 129 mm,`ht=` 也压不住(内容本身就那么高,
tabularray 只能被动撑开)。
不包的话,文字比跨列合计更宽时不会折行,会把整表撑出版心。
本包的对策是 `\lwbodyfont`:
### 常用盒子命令
| 命令 | 用途 |
|---|---|
| `\lwcell{文字}` | 定宽盒子,自动折行 |
| `\lwcellv{文字}` | 同上,垂直居中 |
| `\lwfit{跨度}{文字}` | 按指定跨度定宽 |
| `\lwblank{n}` | 插入 n 个空行位(撑高度) |
| `\lwstack{...}` | 多行堆叠 |
| `\lwsign{跨度}{标签}` | 签字栏 |
| `\lwspanA`…`\lwspanD` | 各格的跨度宽度常量 |
### 签字栏
```latex
\newcommand{\lwbodyfont}{\linespread{1}\relax\fontsize{14}{15.6}\selectfont}
\AtBeginDocument{\lwbodyfont}
\lwsign{\lwspanA}{批准单位负责人签字}
& & \lwsign{\lwwc}{用工单位负责人签字}
& \lwsign{\lwwd}{经办人签字} \\
```
`\AtBeginDocument` 那一次不能省——ctex 在 begin document 时会重设 `\linespread`。
跨度常量 `\lwwa`–`\lwwd` 与 `\lwspanA`–`\lwspanD` 对应各列。
### 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)
A4,单页
正文宋体,表格内文字用 \songti 显式指定
```
漏算的后果很隐蔽:`\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。
示例内容为虚构数据,使用时整段替换。