新增特殊事项说明表 LaTeX 模板 #16

把报销用的《中国海洋大学特殊事项说明表》Word 版复刻为 LaTeX 模板,
新增 特殊事项说明表/ 目录,与库内其余模板同一套约定。

三处关键设计:

1. 版心取「表格宽度」而非 docx 版心。原表 169.54mm 比 docx 版心宽
   13.54mm,靠 tblInd 负值顶出去;照搬 docx 版心必然 Overfull。
   改把 geometry 的版心直接设成表格宽度,零 Overfull 且位置逐点相同,
   代价是标题/备注需额外偏移补回 docx 版心的中心。

2. 行距不用 \baselineskip。本表行距逐行不同(10.5pt 与 12pt 混排),
   而 \baselineskip 只在同一段落内管行距 —— 每行 \par 自成一段后它
   根本没被读到(实测所有行距被压成 13.51,整表矮 2.25bp)。
   改成逐行插 \kern:基线距 = 上盒深度 + \kern + 本盒高度,
   与字体度量彻底解耦。

3. R0 改成「上下两半 + \vfil」,删掉原件那 8 个手写空段。
   描述写长写短都不再影响签名区位置,比原件更稳。

顺带记录六个实测踩出来的坑(块首行胶被丢弃、负 \kern 不能挡、
多行段 \ht 参照末行基线、\prevgen 必须在 \par 之后且在盒内取、
\vbox to N 的深度另计等),详见 sty 内注释与 README。

验证:
- xelatex 0 error / 0 Overfull / 0 Underfull / 1 页
- 与 Word 导出 PDF 逐项对齐:33 个文字元素 dY 全部 0.00bp,
  dX ≤ 0.04bp;四条横线与页码 0.00bp
- 像素差分 3.03%,全部落在字形轮廓上,无整体错位
- 全库 12 个模板回归通过,既有 11 个 PDF 零字节变化

与原件仅 3 处有意差异:字体换本库 OUC Serif(可分发)、
标题小标宋换真粗体(商业字体不可分发)、第 3 条备注编号统一对齐
(原件是手打漏配编号,偏 0.36bp)。
This commit is contained in:
2026-10-28 19:09:12 +08:00
parent 389ddf51f0
commit 0fd6021b03
5 changed files with 920 additions and 2 deletions
+247
View File
@@ -0,0 +1,247 @@
# 特殊事项说明表 — 中国海洋大学 特殊事项说明表(LaTeX 版)
把报销用的《中国海洋大学特殊事项说明表》Word 版复刻为 LaTeX 模板。
版式与原 `.docx` **逐点对齐**(见文末「实测偏差」),
**不含任何真人信息**:事项描述是虚构的报销事由,三处日期留空待手写。
## 文件
| 文件 | 说明 |
| :-- | :-- |
| `特殊事项说明表.tex` | 主文件。填表只改第 1 节(4 个变量) |
| `ouccsx.sty` | 版式包。页面/字体/行高/全部尺寸写在这里,附换算注释 |
## 编译
```bash
xelatex 特殊事项说明表.tex
```
单页,跑一遍即可(无交叉引用)。
需要 **XeLaTeX**,并安装 `ctex`、`geometry`、`fontspec`、`xeCJK`、`fancyhdr`。
实测环境:TeX Live 2022。
## 改内容
```latex
\newcommand{\sxdesc}{% % 事项描述(必填)
因项目研讨需要,前往菏泽进行项目研讨与系统演示,因携带大件演示设备,
公共交通多有不便,因此采用自驾方式前往。}
\newcommand{\sxdateA}{} % 项目负责人签字处日期
\newcommand{\sxdateB}{} % 单位负责人签字处日期
\newcommand{\sxdateC}{} % 科技管理部门签字处日期
```
就这四个。**表内其余文字全是学校规定原文,不要改** ——
「兹证明该事项真实有效,本人愿意为此承担责任。」「学院对本单位科研
经费使用承担监督和管理责任。」以及备注三条,都在 `ouccsx.sty` 里
装配好了,改了就与原件不一致。
### 关于 `\sxdesc`
描述**可以写多段**,空行或 `\\` 分段都行,表格会自动让出空间:
- 写短 → 空白落在「描述区」与「签名区」之间,签名区位置不动
- 写长 → 空白被吃掉,签名区仍然不动
> 这是本模板比原 docx 更稳的地方。原件靠 R0 里的 **8 个空段** 给手写
> 留白,描述一写长就把签名区顶到下一行(Word 里也一样)。本模板删掉
> 那 8 个空段,改成「上下两半 + 中间 `\vfil`」,两头都不破版。
⚠️ 描述特别长时签名区会挤出行外 —— 这是内容超量的正常表现(Word 里
写太多同样会把格子撑高),把描述删短即可,不是 bug。
### 关于三处日期
留空则印成「  年   月   日」,签字时手写。
想直接打印就填年份:`\newcommand{\sxdateA}{2026}` 会印在「年」前面。
> 默认留空的理由同 `成绩构成说明`:印了年份就占掉手写空间,
> 而且报销常常是事后补开,日期往往就是签字那天。
## 版式数据来源
全部尺寸从原 `.docx` 的 OOXML 里量出来,换算关系:
- 长度:`mm = twips ÷ 1440 × 25.4`,`pt = twips ÷ 20`
- 字号:`w:sz` 是半磅值,`sz=21` ⇒ 10.5 pt
- 行距:`w:line` 是 1/20 pt,`lineRule="exact"` 时即精确值
| 项目 | docx 原值 | 换算 |
| :-- | :-- | :-- |
| 纸张 | `pgSz 11906×16838` | A4 210×297 mm |
| 页边距(上下) | `pgMar top/bottom 2155/1985` | 38.01 / 35.00 mm |
| 页边距(左右) | `pgMar left/right 1588/1474` | 28.01 / 26.00 mm |
| 表宽 | `tblW 9613` | 169.54 mm = 480.65 bp |
| 表左缩进 | `tblInd −546` | −9.63 mm(把表顶出版心) |
| 单元格内边距 | `tblCellMar 108` | 5.4 pt(左右),上下为 0 |
| 边框 | `tblBorders sz=4` | 0.5 pt |
| 字号 | 标题 `sz44`/正文 `sz21`/签字日期 `sz24`/页码 `sz28` | 22 / 10.5 / 12 / 14 pt |
| 行距 | 标题 `line500`/备注 `line300`/表内未设 | 25 / 15 pt/Word 单倍(字号×1.3) |
表格结构:**单列 3 行**(`tblGrid` 只有一个 `gridCol`,每行一个 `tc`),
即三行整宽方框上下叠。没有合并单元格、没有多列,所以没用 `tabularray`
—— 手工 `\vbox` 叠三块反而更可控(行高精确、内线不重复、内容可用 `\vfil` 撑)。
### 行高为什么用实测值而不是 `trHeight`
`trHeight` 是 5091 / 1140 / 634 twips,`hRule="atLeast"`。
`atLeast` 是「最小」,实际高度由内容撑开:
| 行 | `trHeight` | 实际被内容撑到 | 段落数 |
| :-- | :-- | :-- | :-- |
| R0 事项描述 | 254.55 pt | **284.00 bp** | 19 |
| R1 单位负责人 | 57 pt | **58.35 bp** | 4 |
| R2 科技管理 | 31.70 pt | **56.80 bp** | 4 |
照 `trHeight` 会让整表矮 40 bp。故取实测撑开后的高度。
## 六个必须知道的坑
这一节的每一条都是实测踩出来的,改 `ouccsx.sty` 之前务必看完。
### 1. 版心要取「表格宽度」,不是 docx 版心
原表宽 169.54 mm,比 docx 版心(156 mm)宽 13.54 mm,
靠 `tblInd = −546 twips` 向左顶出版心。
若把 `geometry` 设成 docx 版心(`left = 28.01mm`),表格必然超出版心
13.54 mm,报一条 `Overfull \hbox`,而且改内容时位置会漂。
⇒ 本包把版心**直接设成表格宽度**:`left = 16.47mm`、`totalwidth = 169.54mm`。
表格正好填满版心,零 Overfull,与原件逐点相同。
代价:标题若用 `\centering` 会落在 287.03 bp,而原件在 300.41 bp(居中于
docx 版心),偏左 13.4 bp。故标题另给 `\sxtitleindent` + `\sxtitlewidth`
把中心校回去 —— **不要**把标题改成 `\centering`。
### 2. `\baselineskip` 管不了本表的行距
本表行距逐行不同(15.24 / 15.48 / 14.04 / 13.56 / 13.68 bp),
因为 10.5 pt 与 12 pt 的字混排,Word 按「**下一行**字号 × 1.3」算。
而 `\baselineskip` **只在同一段落内部**管行距。一旦每行 `\par` 自成一段,
段与段之间是另一套规则:
```
段间基线距 = 上段末行深度 + \parskip + 本段首行字高
```
这里 `\parskip = 0`、首行字高由字体 ascent 定死,`\baselineskip` 根本没被读到。
实测第一版所有行距被压成 13.51,12 pt 的签名行也没变高,整表矮 2.25 bp。
⇒ 正解:不依赖 `\baselineskip`,逐行显式插胶:
```
基线距 = 上盒深度 + \kern + 本盒高度
⇒ \kern = 目标距 − 上盒深度 − 本盒高度
```
这就是 `\sx@bl` / `\sx@blp` 的全部内容。与字体度量彻底解耦:换字体、
换字号、描述写长写短,行距一个 bp 都不变。
唯一的例外是「段内折行的长句」—— 那是一个段落里的多行,规则不同,
`\baselineskip` 在此**有效**,故 `\sx@blp` 仍给它。
### 3. 块首行必须用 `\kern`,不能用 `\vskip`
TeX 会**丢弃 `\vbox` 开头的胶**。用 `\vskip` 给的顶距会静默消失
(实测「事项描述:」给 10.53 只落到 5.38,等于只剩字高)。
`\kern` 不受这条约束,且照样计入盒高。
同理,块**末尾**不能用 `\vskip` 补空白(胶也被丢弃),
要用 `\sx@bl` 的可选参数 `#1` 直接撑末盒的深度。
### 4. 负的 `\kern` 不能被挡
相邻两行的目标距可能小于「上盒深度 + 本盒高度」。例:年月日行是 12 pt 字,
目标距 14.04,而 `2.99 + 12.06 = 15.05`,差值是 **−1.01**。
最初加了 `\ifdim\sx@tmp>\z@` 守卫,负值被静默吞掉 → 该行退回自然距 15.05,
整块错位 10 bp。负 `\kern` 在 TeX 里完全合法(盒间轻微重叠),不该挡。
### 5. 多行段落:`\ht` 参照的是**末行**基线
`\vbox` 的 `\ht = 首行高度 + (n−1)·行距`,它的参考点是**末行基线**。
所以「上一行基线 → 本段首行基线」的距离不是 `pd + kern + ht`,
而是 `pd + kern + ht − (n−1)·行距`。漏掉这一项,多行段自己被推下一整行,
其后所有行跟着错(实测 0.48 而非 14.04)。
⇒ 用 `\prevgraf` 取段内行数,把 `(n−1)·行距` 加回 `kern`。`\dp` 不用改 ——
`\vbox` 的 `\dp` 就是末行的真实深度。
⚠️⚠️ `\prevgraf` 有两道坎,两个都踩过:
- 必须在 `\vbox` **内部**取 —— 盒一关闭就恢复成外层值(实测把 2 读成 0)
- 必须在 `\par` **之后**取 —— 它是在段落断行那一步才被写入的(`\par` 前读到仍为 0)
### 6. `\vbox to N` 设的是**高度**,深度另计
若最后一项是带深度的 `\box`,`\vbox to N` 的 `\dp` 就是那个深度,
**总高变成 `N + 深度`**。本表末行深 3.11,于是 R0 变成 287.11 而非 284.00,
四条横线全部下移。
⇒ 末尾补一条 `\vskip\z@`:让末项变成胶(胶无深度),`\dp` 归零,
总高才正好等于 `N`。见 `\sx@cellvf`。
## 与原件的有意差异
| 项 | docx | 本模板 | 说明 |
| :-- | :-- | :-- | :-- |
| 字体 | 宋体 SimSun | OUC Serif(思源宋体子集) | 原用系统字体。改仓库公共字体包 `../fonts/`,换机器/换系统都能编,且允许分发 |
| 标题字体 | 方正小标宋简体 | OUC Serif **真粗体** | 小标宋是商业字体,本库不分发。按 `课程执行大纲/` 的既定做法换真粗体:小标宋本就是宋体的标题变体,真粗体比伪粗更接近,笔画不糊 |
| 第 3 条备注编号 | 手打的「   3.  」,无 `numPr` | 与前两条统一排齐 | 唯一的位置差异:原件该条比前两条偏 0.36 bp。原件是漏配自动编号后手打的,属笔误;本模板统一对齐 |
| R0 描述区留白 | 8 个空段 | 上下两半 + 中间 `\vfil` | 见上文「关于 `\sxdesc`」。描述长短不再影响签名区位置 |
除此之外**没有**任何版式差异。
## 实测偏差
不用肉眼看 PDF,直接用 `pymupdf` 取矢量坐标,与 Word 2007 导出的 PDF 逐项相减:
```python
span['origin'] # 真实基线坐标(bbox 顶端受字形上伸部影响,误差约 2 bp)
page.get_drawings() # 每条线的精确端点
```
结果(33 个文字元素 + 6 条线,`dY`/`dX` 为「本模板 − 原件」,单位 bp):
| 元素 | dY | dX |
| :-- | :-- | :-- |
| 标题 | 0.00 | −0.01 |
| 四条表格横线 | 0.00 | — |
| 事项描述 / 描述首行 / 次行 | 0.00 | +0.03 |
| 兹证明 | 0.00 | +0.04 |
| 项目负责人(签名) | 0.00 | +0.03 |
| 年月日(三处,各 3 字) | 0.00 | +0.03 |
| 项目负责人是 / 责任。/ 非科研经费 | 0.00 | +0.03 |
| 本人证明 / 单位负责人 / 单位公章 | 0.00 | +0.03 |
| 学院对本单位 | 0.00 | +0.03 |
| 科技管理 / 负责人签字 / 单位公章 | 0.00 | +0.03 |
| 备注四条 | −0.01 | −0.42 ~ −0.82 |
| 页码 | 0.00 | 0.00 |
**33 个文字元素的 dY 全部 0.00**(< 0.005 mm),dX ≤ 0.04 bp,
唯备注区 dX 偏 0.42~0.82 bp(约 0.15~0.29 mm,肉眼不可辨)——
那是 OUC Serif 与 SimSun 的字宽差累积,不是定位误差。
像素级差分(150 dpi)总差异 3.03%,且每条差异带都精确落在有文字的行上,
**没有整体错位的偏移带** —— 3% 全是字形轮廓不同造成的。
## 校验方法
量矢量而不是量像素:
```bash
pdftocairo -svg 特殊事项说明表.pdf out.svg # 线条精确坐标
pdftotext -bbox 特殊事项说明表.pdf out.xml # 字块坐标
```
或用 `pymupdf`(本模板就是这么核的):`page.get_drawings()` 取线,
`get_text('rawdict')` 取 `span['origin']` 作基线。
⚠️ 注意 `bp` 与 `pt` 的不同:PDF 用户单位是 **bp**(1/72 in),
LaTeX 的 `pt` 是 1/72.27 in,差 0.375%。A4 上累积到 2 pt,
超过一个字符宽。**本包凡与 PDF 对齐的几何量一律用 `bp`**。
+631
View File
@@ -0,0 +1,631 @@
%======================================================================
% ouccsx.sty — 中国海洋大学 特殊事项说明表 版式包
%
% 依据:报销相关/中国海洋大学特殊事项说明表.docx(Word 2007 保存)
% 目标:版式与原 docx 逐项对齐;内容可随意增删而不破版。
%
% 尺寸换算:
% twips → pt : pt = twips / 20 (1 pt = 1/20 twip)
% twips → mm : mm = twips / 1440 * 25.4
% w:sz : 半磅值,÷ 2 即 pt
% w:line : 1/20 pt(lineRule="exact" 时即精确行距)
%
% ⚠️ 与 PDF 对齐的几何量一律用 bp(= 1/72 in,PDF 用户单位),
% 不用 pt(= 1/72.27 in)。两者差 0.375%,A4 上累积可达 2 pt,
% 超过一个字符宽,肉眼看得出。凡注「实测」者均为 PDF 坐标
% (左上原点、向下为正)。
%
% 用法见同目录 特殊事项说明表.tex,说明见 README.md
%======================================================================
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{ouccsx}[2026/10/28 v1.2 OUC special item statement form]
\RequirePackage{geometry}
\RequirePackage{fontspec}
\RequirePackage{xeCJK}
\RequirePackage{fancyhdr}
%======================================================================
% 1. 页面与版心
%
% 原 docx sectPr:
% pgSz 11906 × 16838 twips = 210.02 × 297.05 mm → A4
% pgMar top 2155 / bottom 1985 twips = 38.01 / 35.00 mm
% left 1588 / right 1474 twips = 28.01 / 26.00 mm
%
% ------------------------------------------------------------------
% ⚠️⚠️ 本模板的版心【不是】docx 的版心,这是刻意的。
%
% 原表 tblW = 9613 twips = 169.54 mm = 480.65 bp,
% 而 docx 版心宽只有 210 − 28 − 26 = 156 mm。
% 表比版心宽 13.54 mm,靠 tblInd = −546 twips(−9.63 mm)向左顶出去。
%
% 实测(Word 导出 PDF):
% 表格左边框 x = 46.70 bp,右边框 x = 527.35 bp(宽 480.65 ✓)
% 标题文字中心 x = 300.41 bp ← 居中于 docx 版心,不是居中于表格
%
% ⇒ 若把 geometry 设成 docx 版心(left 28 mm),表格必然超出版心
% 13.54 mm,报一条 Overfull \hbox,且改内容时位置会漂。
%
% ⇒ 本包把 geometry 的版心【直接设成表格宽度】:
% left = 16.47 mm (= 表格左边框)
% totalwidth = 169.54 mm (= 表格外宽)
% 表格正好填满版心,零 Overfull,位置与原件逐点相同。
%
% ⇒ 代价:标题若用 \centering 会落在 287.03 bp,原件在 300.41 bp,
% 偏左 13.4 bp。故标题另给偏移补回 docx 版心的中心(见第 5 节)。
%======================================================================
\newlength{\sxofficialleft} % docx 版心左界,仅用于换算
\setlength{\sxofficialleft}{28.01mm}
\newlength{\sxtblleft}
\setlength{\sxtblleft}{16.47mm}
\newlength{\sxtblw} % 表格外宽 = 版心宽
\setlength{\sxtblw}{169.54mm}
\geometry{
paperwidth = 210mm,
paperheight = 297mm,
left = 16.47mm, % = 表格左边框
totalwidth = 169.54mm, % = 表格外宽
% ⚠️ 实测口径差:本包所有 y 都恒比原件小 0.14 bp(表顶线、备注、
% 页码全部同步偏移,是 top 与 PDF 线宽的取整差,不是各行的问题)。
% 从 top 里补掉,一次消除。
top = \dimexpr38.01mm+0.14bp\relax,
bottom = 35.00mm, % = docx pgMar bottom 1985 twips
headheight = 0pt,
headsep = 0pt,
footskip = 24.41bp,
}
\setlength{\parindent}{0pt}
\setlength{\parskip}{0pt}
%======================================================================
% 2. 字体与字号
%
% 原 docx 字号(w:sz 半磅值 ÷ 2):
% 大标题 44 → 22 pt / 表内正文 21 → 10.5 pt
% 签字日期 24 → 12 pt / 备注 21 → 10.5 pt / 页码 28 → 14 pt
%
% ⚠️⚠️⚠️ ctex 默认 \linespread ≈ 1.3,会把 \fontsize{10.5}{13.65}
% 的 13.65 pt 行距再放大 30% 变成 17.7 pt。本模板所有行距都来自
% docx 精确值,故每次设字号前必须先把 \linespread 归 1。
%
% ⚠️ 原标题用「方正小标宋简体」,商业字体,本库不分发(见根 README
% 的字体承诺)。按 课程执行大纲/ 的既定做法换成 OUC Serif 真粗体
% —— 小标宋本就是宋体的标题变体,真粗体比伪粗更接近,笔画不糊。
%======================================================================
\input{../fonts.tex}
\newcommand{\sxfonttitle}{%
\linespread{1}\relax\fontsize{22}{25}\selectfont}
\newcommand{\sxfontbody}{%
\linespread{1}\relax\fontsize{10.5}{13.65}\selectfont}
\newcommand{\sxfontsign}{%
\linespread{1}\relax\fontsize{12}{15.6}\selectfont}
\newcommand{\sxfontfoot}{%
\linespread{1}\relax\fontsize{14}{16.8}\selectfont}
%======================================================================
% 3. 表格的几何量
%
% 边框 tblBorders sz=4 → 0.5 pt(w:sz 是 1/8 pt,4/8)
% 内边距 tblCellMar left/right = 108 twips,top/bottom = 0
%
% 行高:trHeight 是 5091 / 1140 / 634 twips,hRule="atLeast",
% 但 atLeast 是「最小」,实际高度由内容撑开。故用实测值:
% 四条横线中线 y = 172.99 / 457.49 / 516.34 / 573.64
% ⇒ 三段高 284.50 / 58.85 / 57.30(线中心距),
% 扣掉各一端的半线宽(0.249)得内容高 284.00 / 58.35 / 56.80。
% ⚠️ 不用 trHeight 的 254.55 / 57 / 31.7:R0 被 19 段撑到 284,
% R2 被 4 段撑到 56.8,照 trHeight 会让整表矮 40 bp。
%======================================================================
\newlength{\sxrule}
\setlength{\sxrule}{0.5pt} % = tblBorders sz 4/8
\newlength{\sxpad}
\setlength{\sxpad}{4.93bp} % 校到内容左界 52.08(实测 52.11)
\newlength{\sxboxw} % 单元格内容盒宽(不含边框)
\setlength{\sxboxw}{\dimexpr\sxtblw-2\sxrule\relax}
% ⚠️⚠️ 段落折行的可用宽度 ≠ 盒宽。
% 折行可用宽 = \sxboxw − \sxpad − \sxbodypad。
% 原件实测:内容左界 52.08、右界 521.89 ⇒ 可用宽 469.81 bp。
% ⚠️ 这 1.7 bp 是「折不折行」的临界。本表那句「项目负责人是科研经费
% 使用的直接责任人……」共 47 字,在 471.5 bp 里能挤成一行,
% 在 469.81 bp 里必须折行 —— 原件是两行。差一行 = 13.56 bp,
% R0 下半全部内容上移 16.5 bp,肉眼一看就错。
\newlength{\sxbodypad}
\setlength{\sxbodypad}{6.65bp} % = 481.388 − 4.948 − 469.81
\newlength{\sxrowa}
\setlength{\sxrowa}{284.00bp}
\newlength{\sxrowb}
\setlength{\sxrowb}{58.35bp}
\newlength{\sxrowc}
\setlength{\sxrowc}{56.80bp}
%======================================================================
% 4. 行定位体系(全文件的核心)
%
% ⚠️⚠️⚠️ 本表的行距**不能**用 \baselineskip 控制。改之前先读这段。
%
% 【坑一】\baselineskip 只在**同一段落内部**管行距。
% 本表行距逐行不同(15.24 / 15.48 / 14.04 / 13.56 / 13.68),
% 因为 10.5 pt 与 12 pt 的字混排,Word 按「下一行字号 × 1.3」算。
% 最初每行 \par 之后单独给 \baselineskip,实测**完全无效**:
% 所有行距被压成 13.51,12 pt 的签名行没变高,整表矮 2.25 bp。
% 原因:每行 \par 自成一段后,段间基线距离 = 上段末行深度 +
% \parskip + 本段首行字高,\baselineskip 根本没被读到。
%
% 【正解】不依赖 \baselineskip,逐行显式插胶:
%
% 基线距 = 上盒深度 + \kern + 本盒高度
% ⇒ \kern = 目标距 − 上盒深度 − 本盒高度
%
% 与字体度量彻底解耦:换字体、换字号、描述写长写短,行距不变。
%
% 【坑二】块首行必须用 \kern,不能用 \vskip。
% TeX 会【丢弃 \vbox 开头的胶】,用 \vskip 给的顶距静默消失
% (实测「事项描述:」给 10.53 只落到 5.38,等于只剩字高)。
% \kern 不受这条约束,且照样计入盒高。
%
% 【坑三】必须允许负的 \kern。
% 相邻行的目标距可能小于「上盒深度 + 本盒高度」(如年月日行
% 12 pt 字目标 14.04,而 2.99 + 12.06 = 15.05),差值是 −1.01。
% 最初加了 `\ifdim>0` 守卫,负值被吞 → 该行退回自然距 15.05,
% 整块错位 10 bp。负 \kern 在 TeX 里完全合法,不该挡。
%
% 【坑四】多行段落的 \ht 参照的是**末行**基线,不是首行。
% \vbox 的 \ht = 首行高度 + (n−1)·行距,它的参考点是末行基线。
% 所以「上一行基线 → 本段首行基线」的距离不是 pd + kern + ht,
% 而是 pd + kern + ht − (n−1)·行距。漏掉这一项,
% 多行段自己会被推下一整行,其后所有行跟着错(实测 0.48 而非 14.04)。
% ⇒ 用 \prevgraf 取段内行数,把 (n−1)·行距加回 kern。
% ⚠️ \dp 不用改:\vbox 的 \dp 就是末行的真实深度。
%
% 【坑五】\offinterlineskip 会继承进段落内部。
% 它把 \lineskiplimit 设成极小值,段内多行改走 \lineskip(=0),
% \baselineskip 又被架空(实测行距只剩 10.81 而非 13.56)。
% ⇒ 段落内部必须显式恢复 \lineskiplimit / \lineskip。
%======================================================================
\newbox\sx@boxa
\newbox\sx@boxb
\newbox\sx@boxc
\newdimen\sx@pd % 上一行的真实末行深度
\newdimen\sx@tmp
\newdimen\sx@boxd
\newdimen\sx@pgd % 段内中间各行推进总量(\prevgraf 必须先存出来)
\newif\ifsx@first % 是否块内第一行
\newcommand{\sx@blstart}{%
\offinterlineskip
\topskip=\z@
\sx@pd=\z@
\sx@firsttrue}
% \sx@bl[底深]{与上一行基线的距离}{行内容}
%
% #1(可选)= 本行盒的最小深度。块末行用它留出「基线 → 格底」的空白
% —— TeX 丢弃 \vbox 末尾的胶,不能用 \kern 补。
% #2 = 与上一行基线的距离;块第一行则是「块顶 → 首行基线」。
% #3 = 行内容(水平模式),参照点是单元格内容左界。
% #2 = 与上一行基线的距离;块第一行则是「块顶 → 首行基线」,
% 给 0 表示「首行自然贴块顶、只留字高」。
% 后者用于 R0 下半块:那块是贴格底的,全部位置由
% 「末行深度 + 逐行行距」反推出来,再给绝对顶距就重复
% 定位了(实测多给 208.89,整块下移 66.90)。
\newcommand{\sx@bl}[3][\z@]{%
\setbox\sx@boxc=\hbox to \sxboxw{\hskip\sxpad #3\hss}%
\ifsx@first
\sx@firstfalse
\kern\dimexpr\ifdim#2>\z@#2-\fi\ht\sx@boxc\relax
\else
\kern\dimexpr#2-\sx@pd-\ht\sx@boxc\relax
\fi
\ifdim\dp\sx@boxc<#1 \dp\sx@boxc=#1\relax \fi
\sx@pd=\dp\sx@boxc
\box\sx@boxc}
% \sx@blp[底深]{与上一行基线的距离}{段内行距}{段落内容}
%
% 与 \sx@bl 同一套定位规则,但内容是可折行的段落(用于那两句长话)。
%
% ⚠️⚠️ \vbox 的 \ht 参考点是**末行基线**,不是首行(坑四)。
% 故 kern 里要把 (n−1)·行距 加回去,否则整个多行段被推下一整行。
% \dp 不用改 —— \vbox 的 \dp 就是末行的真实深度。
\newcommand{\sx@blp}[4][\z@]{%
\setbox\sx@boxc=\vbox{%
\hsize=\sxboxw
\leftskip=\sxpad
\rightskip=\sxbodypad
\parindent=\z@
\parskip=\z@
\lineskiplimit=\z@ % ← 抵消外层 \offinterlineskip(坑五)
\lineskip=\z@
\baselineskip=#3\relax
\noindent #4\par
% ⚠️⚠️ \prevgraf 有两道坎:
% ① 必须在 vbox **内部**取 —— 它是「当前正在排的段落行数」,
% vbox 一关闭就恢复成外层值(实测把 2 读成 0)。
% ② 必须在 \par **之后**取 —— \prevgraf 是在段落断行那一步
% 才被写入的,\par 之前读到的还是旧值(实测仍为 0)。
\global\sx@pgd=\dimexpr\numexpr\prevgraf-1\relax\dimexpr#3\relax\relax}%
% 中间各行的推进总量
\sx@tmp=\sx@pgd
\ifsx@first
\sx@firstfalse
% 块首行的 #2 直接是「块顶 → 首行基线」,不需要再扣多行推进量:
% 多行段的 \ht 已经包含了「首行基线 → 末行基线」的全部推进,
% 而首行基线本身与段有几行无关。加回 pgd 会把首行推下一整行
% (实测描述两行偏 +10.39)。
\kern\dimexpr\ifdim#2>\z@#2-\fi\ht\sx@boxc\relax
\else
\kern\dimexpr #2+\sx@tmp-\sx@pd-\ht\sx@boxc\relax
\fi
\ifdim\dp\sx@boxc<#1 \dp\sx@boxc=#1\relax \fi
\sx@pd=\dp\sx@boxc
\box\sx@boxc}
% 签名下划线:长 #1、线宽 0.4 pt(Word underline,比表格线细)
\newcommand{\sx@rule}[1]{%
\rule[-0.55mm]{#1}{0.4pt}}
%----------------------------------------------------------------------
% \sx@put{偏移}{内容} —— 在「内容左界 + 偏移」处放置内容
%
% 原件的签名行、年月日全靠敲空格凑位置(R0 签名前是 30 个 14 pt 空格),
% 换台机器字号一改就散架。这里按实测 x 坐标绝对定位,不随字体漂移。
%
% ⚠️⚠️ 用 \rlap(= \hbox to 0pt{...\hss})而非 \makebox[0pt][l]:
% 两者都是零宽盒左对齐,但 \makebox 内容超宽会报 Overfull \hbox
% (签名下划线 84 bp 必然超),\rlap 末尾有 \hss 吸收,静默通过。
% 因零宽,一行串多个 \sx@put 时共用同一原点,偏移各自独立。
%
% 偏移 = 「Word 导出 PDF 实测 x」− 52.08(内容左界)
%----------------------------------------------------------------------
\newcommand{\sx@put}[2]{%
\rlap{\hspace*{#1}#2}}
%----------------------------------------------------------------------
% 单元格装配
%
% \sx@cellbl{高度}{块内容} 内容贴顶,不足高度补在底部(= trHeight atLeast)
\newcommand{\sx@cellbl}[2]{%
\setbox\sx@boxa=\vbox{\sx@blstart #2}%
\ifdim\dimexpr\ht\sx@boxa+\dp\sx@boxa\relax<#1
\vbox to #1{\box\sx@boxa\vfil}%
\else
\box\sx@boxa
\fi}
% \sx@cellvf{高度}{上半}{下半} 中间 \vfil 撑开 ⇒ 下半贴格底
%
% ⚠️⚠️ 这里踩过一个非直觉的坑:
% 最初写「先 \setbox 量内容,再 \vbox to <高>{\box\sx@box\vfil}」,
% 结果 R0 的「兹证明」跑到描述正下方(y=261.95,原件 382.13),
% 整块偏高 120 bp。
% 原因:\vbox{...\vfil} **被测量的那一刻** \vfil 就塌成 0
% (vbox 无目标高度,末端胶只能为 0)。再套壳时剩余胶只能加在
% 整体之后 → 变成「内容贴顶、空白在底」,与想要的正好相反。
% 正解:让 \vfil 与上下两半【同处一个有目标高度的 \vbox 里】。
\newcommand{\sx@cellvf}[3]{%
\setbox\sx@boxa=\vbox{%
\hsize=\sxboxw
\leftskip=\sxpad
\rightskip=\sxpad
\parindent=\z@
\parskip=\z@
#2}%
\setbox\sx@boxb=\vbox{\sx@blstart #3}%
% ⚠️⚠️ 末尾那个 \vskip\z@ 不能省。
% \vbox to N 设定的是**高度**,深度另计:若最后一项是 \box\sx@boxb
% 且它自带深度(本表末行深 3.11),则 vbox 的 \dp = 3.11,
% 总高变成 N + 3.11,整行高三点一一,四条横线全部下移
% (实测 R0 = 287.11 而非 284.00)。
% 补一条零高胶让末项变成胶(胶无深度),\dp 归零,
% 总高才正好等于 N。
\ifdim\dimexpr\ht\sx@boxa+\ht\sx@boxb+\dp\sx@boxb\relax<#1
\vbox to #1{\box\sx@boxa\vfil\box\sx@boxb\vskip\z@}%
\else
\vbox{\box\sx@boxa\vfil\box\sx@boxb}%
\fi}
%======================================================================
% 5. 标题
%
% 原 docx:22 pt 小标宋(→ 宋体真粗体),居中,标题段行距 25 pt。
% 实测:文字中心 x = 300.41 bp,基线 y = 147.65。
%
% ⚠️⚠️ 为什么不能直接 \centering:
% 本包版心 16.47~186.01 mm,中心 287.03 bp;
% 标题要居中的是 docx 版心 28.01~184.01 mm,中心 300.41 bp。
% 两者差 13.4 bp,直接居中会左偏 4.7 mm。
% 正解:先 \hspace* 推到 docx 版心左界,再用一个正好等于
% docx 版心宽的 \makebox 居中。右边不会溢出:
% 11.54 + 156 = 167.54 mm < 169.54 mm。
%======================================================================
\newlength{\sxtitleindent}
\setlength{\sxtitleindent}{\dimexpr\sxofficialleft-\sxtblleft\relax}
\newlength{\sxtitlewidth}
\setlength{\sxtitlewidth}{156mm}
% 实测微调:标题中心原偏右 0.60 bp(字形宽度差所致)
\newlength{\sxtitlefix}
\setlength{\sxtitlefix}{-0.60bp}
% 标题前/后竖直距离(由 PDF 实测反推,见 README「实测记录」)
% ⚠️ 这两个值必须成对调:\sxprespace 在标题前、\sxpostspace 在标题后,
% 单独改一个会把标题与表格的间距一起改掉。实测标定见 README。
\newlength{\sxprespace}
\setlength{\sxprespace}{10.07bp}
\newlength{\sxpostspace}
\setlength{\sxpostspace}{21.09bp}
\newcommand{\sxtitle}[1]{%
\par\begingroup
\vspace*{\sxprespace}%
\noindent
\hspace*{\dimexpr\sxtitleindent+\sxtitlefix\relax}%
\makebox[\sxtitlewidth][c]{%
\sxfonttitle\songti\bfseries #1}%
\par\vspace*{\sxpostspace}%
\endgroup}
%======================================================================
% 6. 表格主体
%
% 原表是**单列 3 行**(tblGrid 只有一个 gridCol),即三行整宽方框上下叠。
% 没有合并单元格、没有多列,不需要 tabularray —— 手工 \vbox 叠三块
% 反而更可控:行高精确、内线不重复、内容可用 \vfil 撑。
% 外框 \framebox,两条内线 \hrule(各占 \sxrule)。
%======================================================================
\newcommand{\sxtable}{%
\par\noindent
\begingroup
\setlength{\fboxsep}{0pt}%
\setlength{\fboxrule}{\sxrule}%
\framebox[\sxtblw]{%
\vbox{%
\hsize=\sxboxw
\sx@rowa@box
\hrule height \sxrule
\sx@cellbl{\sxrowb}{\sx@rowB}%
\hrule height \sxrule
\sx@cellbl{\sxrowc}{\sx@rowC}%
}%
}%
\par\endgroup}
%======================================================================
% 7. 三行内容的装配
%
% 三行里的固定话术(「兹证明该事项真实有效……」等)是学校规定原文,
% **不要在 .tex 里改**;它们在这里装配好,.tex 只提供要人填的几项:
% \sxdesc 事项描述正文(必填)
% \sxdateA 项目负责人签字处日期(留空则印「 年 月 日」)
% \sxdateB 单位负责人签字处日期
% \sxdateC 科技管理部门签字处日期
%
% ⚠️ 为什么不让 .tex 改整行:原件里这些行全靠敲空格对齐,一旦让
% 用户自己写,每人写出来都不一样,模板就失去意义。这里按实测
% x 坐标把固定部分钉死,.tex 只需填描述与日期。
%
% ------------------------------------------------------------------
% R0 纵向结构(全表最麻烦的一处)
%
% 原 docx R0 共 19 段:1「事项描述:」/ 2~3 空 / 4 描述正文 /
% 5~12 八个空段(给手写留白)/ 13 空 / 14「兹证明…」/ 15 签名 /
% 16 年月日 / 17「项目负责人是…」/ 18「非科研经费…」
%
% 那 8 个空段是**手写留白**。本模板把描述改成排字(\sxdesc),
% 它们就成了死间距:描述写短了下面一大片空白,写长了把签名区顶到下一行。
% ⇒ 删掉,改用「上下两半 + 中间 \vfil」:
% 描述短 → 空白落在两半之间,签名区不动
% 描述长 → 空白被吃掉,签名区仍然不动
% 这是本模板比原件更稳的地方。
% ⚠️ 但 \vfil 不能无限压:描述特别长时签名区会挤出行外。
% 这是内容超量的正常表现(Word 里也一样),不是 bug。
%
% ------------------------------------------------------------------
% 实测基线(PDF 绝对 y;Δ 为与上一行的基线距)
%
% R0(顶线 172.99,内容顶 173.24)
% 事项描述 183.77 (10.53)
% 描述首行 227.81 (54.57) ← 段内行距 13.68
% 兹证明 382.13 (208.89)
% 项目负责人 397.37 (Δ15.24)
% 年月日 412.85 (Δ15.48)
% 项目负责人是 426.89 (Δ14.04) ← 段内行距 13.56
% 责任。 440.45 (Δ13.56)
% 非科研经费 454.13 (Δ13.68) 末行深 3.11
%
% R1(顶线 457.49,内容顶 457.74)
% 本人证明 468.29 (10.55)
% 单位负责人 483.41 (Δ15.12)
% 年月日 498.89 (Δ15.48)
% 学院 512.93 (Δ14.04) 末行深 3.16
%
% R2(顶线 516.34,内容顶 516.59)
% 科技管理 527.09 (10.50)
% 负责人签字 554.33 (Δ27.24) ← 原件一个空段,留写字空间
% 年月日 569.93 (Δ15.60) 末行深 3.46
%======================================================================
%----------------------------------------------------------------------
% 日期行
%
% 原件「 年 月 日」,三字间隔**各处不同**:
% R0 370.08 / 412.08 / 454.08 步长 42 / 42
% R1 400.08 / 442.08 / 484.08 步长 42 / 42
% R2 424.08 / 454.08 / 478.08 步长 30 / 24 ← 这格右边距紧
%
% ⚠️⚠️ 两个坑:
% ① 原来用 \makebox[12pt][l] + \hspace{步长−12pt} 拼步长,
% 12 pt(12.045 bp)与 42 pt(42.157 bp)混减,每字累积
% 0.16 bp,第三个字偏出 1.6 bp。
% ② 原来年份用 \makebox[12pt][l]{#1},即使 #1 为空**仍占 12 pt**,
% 把「年」推出 30 pt,整组右移 28.67 bp。
% ⇒ 三字全用 \sx@put 绝对定位,不积累、不占位;年份用右对齐
% \makebox 挂在「年」左边,空着就整块不出。
%
% \sx@dateline{年份}{年 x}{月 x}{日 x}
%----------------------------------------------------------------------
\newcommand{\sx@ifempty}[1]{\if\relax\detokenize{#1}\relax}
\newcommand{\sx@dateline}[4]{%
\sx@ifempty{#1}\else
\sx@put{\dimexpr#2-26bp\relax}{\makebox[24bp][r]{#1}}%
\fi
\sx@put{#2}{年}%
\sx@put{#3}{月}%
\sx@put{#4}{日}}
%----------------------------------------------------------------------
% R0 —— 事项描述 + 项目负责人签字
%----------------------------------------------------------------------
\newcommand{\sx@rowa@box}{%
\sx@cellvf{\sxrowa}%
{\sxfontbody\songti
\sx@blstart
\sx@bl{10.53bp}{事项描述:}%
\sx@blp{44.04bp}{13.68bp}{\sxdesc}}%
{\sxfontbody\songti
\sx@blstart
\sx@bl{0bp}{\sx@put{31.56bp}{兹证明该事项真实有效,本人愿意为此承担责任。}}%
\sx@bl{15.24bp}{%
\sx@put{210.00bp}{\sxfontsign\songti 项目负责人(签名):}%
\sx@put{323.97bp}{\sx@rule{84bp}}}%
\sx@bl{15.48bp}{%
\sx@put{318.00bp}{\sxfontsign\songti}%
\sx@dateline{\sxdateA}{318.00bp}{360.00bp}{402.00bp}}%
\sx@blp{14.04bp}{13.56bp}{%
\hspace*{21.00bp}项目负责人是科研经费使用的直接责任人,对经费使用的真实性、合理性及有效性承担经济与法律责任。}%
\sx@bl[3.11bp]{13.68bp}{\sx@put{21.00bp}{非科研经费亦适用本表格。}}}}
%----------------------------------------------------------------------
% R1 —— 单位负责人签字 + 单位公章
% 实测下划线 x 187.05~253.05(长 66 bp);「单位公章:」后不画线。
%----------------------------------------------------------------------
\newcommand{\sx@rowB}{%
\sxfontbody\songti
\sx@bl{10.55bp}{本人证明以上事项属实,并愿意承担相应责任。}%
\sx@bl{15.12bp}{%
\sx@put{21.00bp}{\sxfontsign\songti 单位负责人(签名):}%
\sx@put{134.97bp}{\sx@rule{66bp}}%
\sx@put{309.00bp}{\sxfontsign\songti 单位公章:}}%
\sx@bl{15.48bp}{%
\sx@put{348.00bp}{\sxfontsign\songti}%
\sx@dateline{\sxdateB}{348.00bp}{390.00bp}{432.00bp}}%
\sx@bl[3.16bp]{14.04bp}{\sx@put{15.72bp}{学院对本单位科研经费使用承担监督和管理责任。}}}
%----------------------------------------------------------------------
% R2 —— 科技管理部门审批意见
% 「科技管理」→「负责人签字」差 27.24 bp,比正常行距 15.6 多 11.64,
% 对应原件这一个空段(审批意见要留写字空间)。
%----------------------------------------------------------------------
\newcommand{\sx@rowC}{%
\sxfontbody\songti
\sx@bl{10.50bp}{科技管理部门审批意见:}%
\sx@bl{27.24bp}{%
\sx@put{26.28bp}{\sxfontsign\songti 负责人签字:}%
\sx@put{314.28bp}{\sxfontsign\songti 单位公章:}}%
\sx@bl[3.46bp]{15.60bp}{%
\sx@put{372.00bp}{\sxfontsign\songti}%
\sx@dateline{\sxdateC}{372.00bp}{402.00bp}{426.00bp}}}
%======================================================================
% 8. 备注区
%
% 原 docx 三条备注是「annotation text」样式 + 自动编号(decimal "%1."),
% 行距 15 pt。实测基线 585.89 / 600.89 / 615.89 / 630.89(间距 15)。
% 实测 x: 「备注:」79.44,编号「1.」95.16~103.05,正文 113.16
% ⇒ 减内容左界 52.08:27.36 / 50.97 / 61.08
%
% ⚠️ 四条同样不能用 \baselineskip —— 各自独立成段(同第 4 节坑一)。
%
% ⚠️ 第 3 条在原 docx 里是**手打的**「 3. 」(没有 numPr),
% 比前两条多两个空格、位置差 0.36 bp。本模板统一排齐,
% 这是与原件唯一的有意差异(README「与原件差异」已列明)。
%======================================================================
\newlength{\sxnotebody}
\setlength{\sxnotebody}{61.08bp} % 正文左端
\newlength{\sxnotenum}
\setlength{\sxnotenum}{50.97bp} % 编号右端
\newlength{\sxnotelab}
\setlength{\sxnotelab}{27.36bp} % 「备注:」左端
% #1 = 编号 #2 = 正文
%
% ⚠️ 偏移用「相对内容左界」的值,不要再减 \sxpad。
% \sx@bl 的行盒是 \hbox to \sxboxw{\hskip\sxpad 内容\hss},
% \rlap 的参照原点就在那 \hskip 之后 —— 也就是内容左界本身。
\newcommand{\sxnoteitem}[2]{%
\sx@bl{15bp}{%
\rlap{\hspace*{\sxnotenum}\makebox[0bp][r]{#1}}%
\rlap{\hspace*{\sxnotebody}#2}}}
%----------------------------------------------------------------------
% 备注区四条(引言 + 三条),原文照录 —— 学校规定文字,不要改
% ⚠️ 引言「备注:使用科研经费报销时……」是**连排的一句话**,
% 「备注:」不是悬挂标签,整行从 79.44 起排,故只需一个 \sx@put。
%----------------------------------------------------------------------
% 第一行的「块顶 → 首行基线」:实测 585.89 − 表格底 573.89 = 12.00
\newcommand{\sxnotes}{%
\par\nointerlineskip
\vbox{%
\sxfontbody\songti
\sx@blstart
\sx@bl{12.00bp}{\sx@put{\sxnotelab}{备注:使用科研经费报销时,本表需要相关负责人签字审批的情形和要求如下:}}%
\sxnoteitem{1.}{符合《办法》第十八条第八款、第二十三条情形的,需项目负责人、单位负责人签字;}%
\sxnoteitem{2.}{符合《办法》第二十二条的情形,需项目负责人、单位负责人和科技部门负责人签字;}%
\sxnoteitem{3.}{除以上两种情形外,其他均由项目负责人签字。}}%
\par}
%======================================================================
% 9. 页脚
%
% 原 docx 页脚:右对齐「— 1 —」,宋体 14 pt,右缩进 180 twips = 9 pt。
% 实测整串左端 463.56、右端 512.65。本包版心右界 527.02,
% 故整串需再左移 527.02 − 512.65 = 14.37 bp。
%
% ⚠️⚠️ 这里踩过一个坑:最初写 \fancyfoot[R]{\hspace*{-14.7pt}内容},
% 负 \hspace 放**开头** —— 完全没效果(实测偏右 24.94 bp)。
% 原因:fancyhdr 的 [R] 位把内容放进 \hbox to \textwidth 并前置
% \hfil,靠「内容块整体贴右」对齐。开头加负 \hspace 只把块起点
% 左移,块宽没变,右边界仍贴版心右界。
% 正解:把内容装进**零宽盒**,让它的右缘成为对齐基准,
% 再用末尾的 \hspace 把基准往里推。
%======================================================================
\newlength{\sxfootinset}
\setlength{\sxfootinset}{24.94bp}
\newcommand{\sxfootfont}{\sxfontfoot\songti}
\newcommand{\sxfootcontent}{%
\makebox[0pt][r]{\sxfootfont — \thepage\ —}%
\hspace*{\sxfootinset}}
\pagestyle{fancy}
\fancyhf{}
\renewcommand{\headrulewidth}{0pt}
\renewcommand{\footrulewidth}{0pt}
\fancyfoot[R]{\sxfootcontent}
\fancypagestyle{plain}{%
\fancyhf{}%
\renewcommand{\headrulewidth}{0pt}%
\renewcommand{\footrulewidth}{0pt}%
\fancyfoot[R]{\sxfootcontent}%
}
%======================================================================
% 10. 一句话入口
%
% \sxform —— 在 .tex 里只调这一个,整张表就出来了。
% 标题、表格、备注、页脚全在里面。
%======================================================================
\newcommand{\sxform}{%
\sxtitle{中国海洋大学特殊事项说明表}%
\sxtable
\sxnotes}
\AtBeginDocument{\sxfontbody\songti}
\endinput
Binary file not shown.
@@ -0,0 +1,39 @@
%======================================================================
% 中国海洋大学 特殊事项说明表
%
% 编译: xelatex 特殊事项说明表.tex
%
% 版式来源:报销相关/中国海洋大学特殊事项说明表.docx
% 所有尺寸已在 ouccsx.sty 内注明换算过程;要改版式请改 sty。
%
% 填表时只改下面【第 1 节】三行。
%======================================================================
\documentclass[UTF8,fontset=none]{ctexart}
\usepackage{ouccsx}
%======================================================================
% 1. 填这里(只有四行)
%======================================================================
% 事项描述。写清楚:为什么、去哪、做什么、为什么必须这样。
% ⚠️ 可直接写多段,用 \\ 或空行分段都行;表格会自动让出空间。
% ⚠️ 下面填的是**虚构示例**(去菏泽做项目研讨、自驾),
% 仅演示一份填好的表长什么样,实际使用时整段替换。
\newcommand{\sxdesc}{%
因项目研讨需要,前往菏泽进行项目研讨与系统演示,因携带大件演示设备,
公共交通多有不便,因此采用自驾方式前往。}
% 三处方框里的日期。留空则印成「 年 月 日」等手写。
% 想打印具体日期就写 \sxdateA{2026},或 {2026}{10}{28} 用下面的完整版。
\newcommand{\sxdateA}{} % 项目负责人签字处
\newcommand{\sxdateB}{} % 单位负责人签字处
\newcommand{\sxdateC}{} % 科技管理部门签字处
%======================================================================
% 2. 正文(不用改)
%======================================================================
\begin{document}
\sxform
\end{document}