Files
ouc_latex_template/劳务发放说明表
laoyang 8984b93ee7 模板内容填充:全库 × 占位换成完整虚构示例,README 表述同步 #11
把 11 个模板里满篇的 × 换成一套连贯的虚构数据,让样张能看出排版效果。

虚构设定(跨模板统一):
- 数字逻辑 / 2025 秋 / 张远航 / 计算机科学与技术学院,教学日历、成绩构成
  说明、试卷归档封面、试卷四份互相对得上
- 简历:张远航,1985.03,教授博导,论文/专利/项目/获奖全套虚构
- 年度考核:同一人的 2025 年度考核表,年度总结四段写满
- 执行大纲:刻意不套用上面那套(原件就是《信号与线性系统分析》的课,
  强行改课程名会让章节体系、学时分配、思政案例全对不上)

假数据都留肉眼可辨标记:DOI 统一 10.9999/、专利号 ZL209999…、
软著 2024SR99999…、手机 138 0000 0000、邮箱 example.net。
签字/日期/评语栏仍然留空——编了就分不清该改哪儿。

修掉一个既有 bug(填充时才暴露):
年度考核登记表「出生年月」的值从来不显示,连字符都不在 PDF 里。
根因是 tabularray 的 cell{r}{c}={c=n} 里那个 c 是数据行的单元序号、
不是视觉列号,表头三处 c=2 要求该行吃 15 个视觉列而表只有 11 列,
超出部分静默丢弃。迷惑点:写 12 格丢值,写 9 格反而正常。
正解是表头不写 cell{},改用行内 \SetCell[c=n]{c},每行照常写满 11 格。
同时 R0 行原件本就装不下(前六字段 115.76mm,剩 42.20mm 要放
19.68mm 标签 + 17.22mm 值,但列宽被切成 15.31/1.38/25.51),
把标签折两行「出生/年月」解决,列宽一个没改。

README 同步:根 README 与 8 个模板 README 里「一律用 × 占位」的说法
已不成立,统一改为「示例内容全部虚构」,并说明哪些位置仍必须留空。

验证:12 个模板零 error,4 处基线警告未新增;干净副本重编页数一致;
PDF 正文 × 清零;真实信息零泄漏。
2026-10-27 12:50:02 +08:00
..

劳务发放说明表 — 中国海洋大学 劳务发放说明表(LaTeX 版)

把实验室用的《劳务发放说明表》Word 版复刻为 LaTeX 模板。版式与原 .docx 逐项对齐,不含任何真人信息:姓名、人数、项目名称、单位名称全部是编的。

文件

文件 说明
劳务发放说明表.tex 主文件。填表只改第 1 节(4 个变量)
ouclw.sty 版式包。页面/字体/列宽/行高/全部尺寸写在这里,附换算注释

编译

xelatex 劳务发放说明表.tex

单页,跑一遍即可(无交叉引用)。

需要 XeLaTeX,并安装 ctex、geometry、fontspec、xeCJK、tabularray。 实测环境:TeX Live 2022 + tabularray 2022A。

改内容

\newcommand{\lwunit}{{\songti 信息科学与工程学部}}  % 用工单位(学部 / 学院)
\newcommand{\lwreason}{{\songti 科研项目数据整理}}  % 用工事由
\newcommand{\lwnote}{}                            % 备注(可留空)
\newcommand{\lwwork}{%
  聘请{\songti 李承宇}等{\songti 2}位研究生参与《{\songti 近岸海域生态健康
  多源数据融合与智能评估技术}》项目的研究工作。}

上列值是样张实际用的虚构内容(人名校验过:李承宇 不对应任何真实人员)。

关于 \lwwork 的句式

原文是一句「聘请某研究生等 N 位参与某项目研究工作」的表述 —— 真人姓名、人数、真实项目名均未保留,句式一字未动。 填表时把这三处换成实际内容即可:

样张值 含义 换成
李承宇 第一位研究生的姓名 真实姓名("等"字后面若只有一人,可删"等 N 位")
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 会吃掉你设的行距

\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:

\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,直接量矢量:

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。