diff --git a/README.md b/README.md index e835fa6..c685044 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ | 目录 | 内容 | |---|---| | [`exam/`](exam/) | 期末考试**试卷**与**参考答案及评分标准**模板(XeLaTeX) | +| [`form/`](form/) | 教职工**年度考核登记表**模板(XeLaTeX) | ## 说明 diff --git a/form/README.md b/form/README.md new file mode 100644 index 0000000..2ad3c3d --- /dev/null +++ b/form/README.md @@ -0,0 +1,146 @@ +# form/ — 中国海洋大学 教职工年度考核登记表(LaTeX 版) + +把学校下发的 Word 版《中国海洋大学教职工年度考核登记表》复刻为 LaTeX 模板, +版式与原 `.docx` 逐项对齐,**表格里不含任何真人信息**(姓名/职工号/出生年月/ +单位/岗位一律 `×` 占位)。 + +## 文件 + +| 文件 | 说明 | +| :-- | :-- | +| `年度考核登记表.tex` | 主文件。填表只改第 1 节(基本信息)与 `\khsummary`(年度总结) | +| `ouckhtb.sty` | 版式包。页面/字体/列宽/行高/全部尺寸都写在这里,附换算注释 | + +## 编译 + +```bash +xelatex 年度考核登记表.tex +xelatex 年度考核登记表.tex # 跑两遍,第二遍取到正确页码 +``` + +需要 **XeLaTeX**(用 fontspec + xeCJK 调系统字体),并安装: +`ctex`、`geometry`、`fontspec`、`xeCJK`、`tabularray`。 + +实测环境:TeX Live 2022 + `tabularray 2022A`。用 LuaLaTeX 理论上也行,但未验证。 + +产出 2 页、A4、正反面打印正好。 + +## 改内容 + +### 基本信息 + +```latex +\khtbyear{2025} % 表头“×××× 年度”那一行 + +\newcommand{\khnum}{0000000} % 职工号 +\newcommand{\khname}{{\fangsong ××}} % 姓名 +\newcommand{\khsex}{{\fangsong ×}} % 性别 +\newcommand{\khbirth}{{\fangsong ××××.××}} % 出生年月 +\newcommand{\khdept}{{\fangsong ××××××××}} % 单位(学部 / 学院) +\newcommand{\khsubdept}{{\fangsong ××××××××}} % 系(研究所、实验室、科室) +\newcommand{\khparty}{{\fangsong ××××}} % 政治面貌 +\newcommand{\khtitle}{{\fangsong ×××}} % 现专业技术职务 +\newcommand{\khpost}{{\fangsong ×××}} % 所聘岗位 +``` + +> **`{\fangsong ...}` 不能去掉。** 占位符 `×` 是 U+00D7,fontspec 会把它当 +> ASCII 交给 Times New Roman,而那儿的 `×` 是 **1em 宽的数学乘号** +> (14pt 下一个占 14pt),几个就能撑破整列。包上 `\fangsong` 才会按全角汉字宽度排。 + +### 年度总结 + +```latex +\newcommand{\khsummary}{% + 第一段……\par + 第二段……\par + 第三段……} +``` + +段间用 `\par`(不要用空行 —— 空行在 `\newcommand` 参数里会被当成分段但不易数)。 +首行自动缩进 2 字,末行自动带「本人签名 / 年 月 日」,都写在 `ouckhtb.sty` 里。 + +## 版式数据来源 + +所有尺寸都从 `.docx` 内部的 OOXML 数值换算,不使用目测: + +``` +twips → mm : mm = twips / 1440 × 25.4 +twips → pt : pt = twips / 20 (1 pt = 1/72 in) +w:sz : 半磅值,÷ 2 即 pt +``` + +| 项 | docx 值 | LaTeX 值 | +| :-- | :-- | :-- | +| 纸张 | 11907 × 16840 twips | A4(210 × 297 mm) | +| 表宽 `tblW` | 8976 twips | 158.33 mm(11 列 + 边框) | +| 11 个 `gridCol` | 1087 283 1221 1047 284 1105 952 600 870 80 1447 | 见 `ouckhtb.sty` 第 3.1 节 | +| 正文字号 | `w:sz=28` | 仿宋 14 pt / 行距 15.6 pt | +| 大标题 | `w:sz=44`,`w:spacing=-14` | 黑体 22 pt / 字距 −0.7 pt | +| 行高 `trHeight` | 412 460 939 1261 1252 1009 556 1258 1258 | 7.27 / 8.11 / 16.56 / 22.24 / 22.08 / 17.80 / 9.81 / 22.19 / 22.19 mm | + +### 页边距为什么不照抄 docx + +docx 是左右各 30 mm 版心(150 mm),但表宽 158.33 mm 比它还宽 8.33 mm, +Word 是靠 `tblPr/jc=center` 把这张表“压”进页边距里的。 + +本模板把页边距改成 `(210 − 158.33)/2 = 25.835 mm`,使 `\textwidth` 恰好等于表宽: + +- 表格天然居中,不需要 `\leftskip` / `\centerline` 之类的偏移; +- **表格在纸面上的绝对位置与 Word 完全一致**(左右各 25.835 mm); +- 编译时不会刷 `Overfull \hbox`。 + +表外文字(标题、脚注)仍是水平居中,视觉上与 30 mm 版心没有差别。 + +## 排版时的四个坑(sty 里都有详细注释) + +1. **合并单元格不折行。** `cell{r}{c}={c=n}{c}` 的单元类型 `{c}` 是 LR 模式, + 格子里的文字比所跨各列合计更宽时,它**不折行,而是把列撑宽、整表超出版心**。 + 实测「系(研究所、实验室、科室)」把表从 448 pt 撑到 559 pt。 + → 所以合并格里的文字一律包 `\khtbfit{跨度宽宏}{文字}`。 + 单列的 `Q[c,m,wd=…]` 没有这个问题(超了只是溢出,列宽不变)。 + +2. **合并格里的 `\hsize` 没被重设。** span=10 的格子里 `\hsize` 仍是整页版心宽, + 长文本会按 450 pt 折行、冲出格子。→ 长内容必须用定宽 `\parbox`(`\khtbcell`)。 + +3. **跨度声明只有 `{c=n}{c}` 一种写法。** `={c=n}`、`={n}{c}`、`={span=n}{c}` + 都不认,最后那个会报 `The key 'tblr-cell-span/span' is unknown`。 + +4. **`colspec` / `row{}` 里不能放宏。** tabularray 在宏展开之外解析列类型, + 会报 `Unexpandable command … inside column type`。所以列宽只能字面写死。 + +另外两个容易忘的: + +- `longtblr` 默认会把各列按 `\textwidth` 等比拉伸(`tblr` 不会),必须写 `stretch=0`; +- `longtblr` 会在续页处印「表 0: (Continued)」,必须用 `\DefTblrTemplate` 把 + `caption` / `capcont` / `conthead-text` / `contfoot-text` **四个模板全清**。 + +## 与原 docx 的已知差异 + +| 位置 | docx | 本模板 | 说明 | +| :-- | :-- | :-- | :-- | +| 表头「×××× 年度」 | `firstLine` 缩进 2 字、未设居中 | 居中 | 更像原排版疏漏,按意图改居中。想还原就把 `\khtbtitle` 里的 `\centering` 换成 `\hspace*{2\ccwd}` | +| 「师德考核结果」首列 | `师师德考核结果` | `师德考核结果` | docx 原文首字重复(WPS 竖排遗留),已按正常写法更正 | +| 「单位年度考核建议档次」首列 | `单单位年度考核建议档次` | `单位年度考核建议档次` | 同上 | +| 单元格内边距 | 左右各 108 twips(1.905 mm) | 0 | c10 只有 1.41 mm,比两倍内边距还窄,统一内边距会算出负宽。代价是文字可贴竖线,但全部单元格本就水平居中,观感一致 | +| 未勾选框 | Wingdings `¨`(char 0x00A8) | U+25A1 `□` | Wingdings 在 Linux/macOS 上不可靠。仿宋、黑体都有 `□`,**宋体没有** —— 改正文为宋体时需另指方框字体 | +| 电子签名图片 | 内嵌两张手写签名 JPEG | 无 | 模板不含真人信息 | + +## 校验方法(想改版式时照这个验) + +不要靠肉眼看 PDF。用矢量坐标对: + +```bash +xelatex 年度考核登记表.tex +pdftocairo -svg 年度考核登记表.pdf pg.svg # 转成 SVG 取精确线条坐标 +pdftotext -bbox 年度考核登记表.pdf - # 取每个字的 xMin/yMin/xMax/yMax +``` + +正确结果应当满足: + +- 表格左边界 73.14 pt、右边界 520.91 pt(宽度 447.8 pt ≈ 157.96 mm); +- 表格所有横线都是 **10 段**(8 个网格列位置被合并掉,只剩 10 段可见); +- 页数为 2; +- `grep "Overfull\|too small" 年度考核登记表.log` 无输出。 + +当前状态:**零 Overfull、零 Underfull、2 页、表宽 157.96 mm**(目标 158.33 mm, +差 0.23%,为消除 0.45 pt 的 `Overfull` 累积误差而取整所致,肉眼不可辨)。 \ No newline at end of file diff --git a/form/ouckhtb.sty b/form/ouckhtb.sty new file mode 100644 index 0000000..2b535b7 --- /dev/null +++ b/form/ouckhtb.sty @@ -0,0 +1,456 @@ +%====================================================================== +% ouckhtb.sty — 中国海洋大学 教职工年度考核登记表 版式包 +% +% 依据:2025 年学校下发的 Word 表(WPS 保存的 .docx) +% 目标:版式与原 docx 逐项对齐。所有尺寸都由 docx 内部数值换算而来: +% twips → mm : mm = twips / 1440 * 25.4 +% twips → pt : pt = twips / 20 (1pt = 1/72in) +% w:sz : 半磅值,÷2 即 pt +% +% 用法见同目录 年度考核登记表.tex,参数说明见 README.md +%====================================================================== +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{ouckhtb}[2026/10/23 v1.0 OUC staff annual review form] + +\RequirePackage{geometry} +\RequirePackage{fontspec} +\RequirePackage{xeCJK} +\RequirePackage{tabularray} + +%====================================================================== +% 1. 页面与版心 +% +% 原 docx sectPr: +% pgSz 11907 × 16840 twips = 210.03 × 297.04 mm → A4 +% pgMar top/bottom 1418 = 25.01 mm +% left/right 1701 = 30.00 mm +% header 851 / footer 992 = 15.01 / 17.50 mm +% +% 原表宽 tblW 8976 twips = 158.33 mm,比 docx 版心(150 mm)宽 8.33 mm, +% Word 靠 tblPr/jc=center 把它居中压进左右页边距。 +% +% ⚠️ 本包【不】照搬 docx 的 30 mm 页边距,而是取 +% left = right = (210 − 158.33)/2 = 25.835 mm +% 使 \textwidth 恰为 158.33 mm。这样: +% · 表格天然居中,无需 leftskip / \centerline 之类的偏移技巧 +% · 表格宽度 = 版心宽度,编译时不会刷 Overfull \hbox +% · 表格在纸面上的绝对位置与 Word 完全相同(左右各 25.835 mm) +% 正文(表外标题、脚注)仍是水平居中,视觉上与 30 mm 版心一致。 +%====================================================================== +\geometry{ + paperwidth = 210mm, + paperheight = 297mm, + totalwidth = 158.33mm, % = 表宽,精确;不要写 left/right(见下) + hmarginratio = 1:1, % 左右等边距,表格自然居中 + top = 25.01mm, + bottom = 25.01mm, + headheight = 0pt, + headsep = 0pt, + footskip = 17.50mm, +} +\setlength{\parindent}{0pt} +\setlength{\parskip}{0pt} +\pagestyle{plain} + +%====================================================================== +% 2. 字体与字号 +% +% 正文 仿宋 14pt (w:sz=28) +% 表外大标题 黑体 22pt (w:sz=44),docx 另设 w:spacing=-14 +% ⇒ -14/20 = -0.7pt,相对 22pt 即 -3.2% +% “2025 年度”一行 仿宋 16pt (w:sz=32) +% R1C6 的括注 仿宋 12pt (w:sz=24),只有“研究所、实验室、科室” +% 页脚页码 9pt (footer 样式 w:sz=18) +%====================================================================== +\setmainfont{Times New Roman} +\setCJKmainfont{FangSong}[AutoFakeBold=2.5] +\newCJKfontfamily\fangsong{FangSong}[AutoFakeBold=2.5] +\newCJKfontfamily\heiti{SimHei} +\newCJKfontfamily\songti{SimSun} + +% 正文字号;行距 15.6pt 对应 docx docGrid/linePitch=312 twips +\newcommand{\khtbbodyfont}{\fontsize{14}{15.6}\selectfont} +% 括注小字:docx 里“(对考核档次为……需说明原因)”是 12pt (w:sz=24) +\newcommand{\khtbsmallnote}{\fontsize{12}{14}\selectfont} + +% R0C6“系(研究所、实验室、科室)”在 docx 里是混排: +% “系” w:sz=28(14pt),“(研究所、实验室、科室)” w:sz=24(12pt) +% 用下面这个宏按原样排,别整句都用 14pt —— 否则折行位置会与 Word 不同。 +\newcommand{\khtbxi}{\fangsong 系{\fontsize{12}{14}\selectfont (研究所、实验室、科室)\normalfont}} + +%---------------------------------------------------------------------- +% ⚠️ xeCJK 陷阱:局部字体切换命令若紧邻 \par(或落在段落末尾),段末的 +% 字体状态会“溢出”到后面段落,使后续 ASCII 字符被排成别的字体。 +% 故局部切换一律走下面两个包装(内部用 \normalfont 收尾)。 +%---------------------------------------------------------------------- +\newcommand{\KHTBFS}[1]{{\fangsong #1\normalfont}} +\newcommand{\KHTBHT}[1]{{\heiti #1\normalfont}} + +%====================================================================== +% 3. 列的宽度模型(本包最关键的一节,改之前请先读完) +% +% 原 docx tblGrid(11 个网格列,twips → mm): +% c1 1087→19.17 c2 283→ 4.99 c3 1221→21.54 +% c4 1047→18.47 c5 284→ 5.01 c6 1105→19.49 +% c7 952→16.79 c8 600→10.58 c9 870→15.35 +% c10 80→ 1.41 c11 1447→25.52 +% 合计 8976 twips = 158.33mm(与 tblW 一致) +% +% 各行的合并跨度(docx gridSpan,每行之和均为 11): +% R0 2,1,1,2,1,1,1,2 (8 个单元) +% R1 2,3,2,4 (4 个单元) +% R2 2,1,2,2,3,1 (6 个单元) +% R3~R8 1,10 (2 个单元:标签 + 内容栏) +% +%---------------------------------------------------------------------- +% ⚠️⚠️ 四条实测结论(tabularray 2022A),决定了下面的写法: +% +% (a) tabularray 的 wd 是“内容宽”,不含任何内边距;表宽 = Σwd + 竖线宽。 +% 而 Word 的 gridCol 是“含内边距的整格宽”。两者语义相反。 +% +% tabularray 计宽时按 11 根竖线算(左边界那根不算),即 Σwd + 11×0.5pt +% = Σwd + 5.5pt。要让它恰好等于表宽 158.33mm,需 +% Σwd = 158.3267mm − 5.5pt = 158.3267 − 1.9329 = 156.3938mm +% 而 ΣgridCol = 158.3267mm,故每列要减 (158.3267−156.3938)/11 +% = 0.1757mm。(gridCol − 0.1757) 即下面 3.1 节的取值。 +% +% ⚠️ 曾经取 0.1917mm(按 12 根竖线 6pt 算),表宽少 0.5pt, +% longtblr 会一直报 “Table width is too small, need 0.50008pt more!” +% 外加一条 0.5pt 的 Overfull \hbox。差得极小但很碍眼,故校正。 +% +% (b) Word 的 tblCellMar 左右各 108 twips(1.905mm)。本包【不】复现这个 +% 内边距,而取 colsep=0、内容可用宽 = 整格宽。原因:c10 只有 1.41mm, +% 比两倍内边距(3.81mm)还窄,统一 colsep 必然把该列算成负宽而报错。 +% 代价:单元格文字可以贴到竖线上。本表所有单元格都是水平居中,且 +% 窄列标签(如“出生年月”)在 Word 里本来就要折成两行,观感一致。 +% +% (c) ⚠️ 合并单元格(\SetCell[c=n])里的 \hsize【没有】被重设成该跨度的 +% 宽度,它仍是外层版心宽。实测:span=10 的格子里 \linewidth=47.8pt +% 但 \hsize=450.5pt,于是长文本按 450pt 折行、彻底冲出格子 +% (这就是曾经那个 “Overfull \hbox (1644pt too wide)” 的真正来源)。 +% ⇒ 凡是内容较长或含多段的跨列单元格,必须用固定宽的 \parbox 包起来。 +% +% (d) ⚠️⚠️⚠️【最要命的一条】跨列合并格 cell{r}{c}={c=n}{c} 的单元类型 +% {c} 是【不折行的 LR 模式】。格内文字若比所跨各列的合计宽,它不会在 +% 列内折行,而是【把这些列撑宽】,整张表随之超出版心。 +% 实测:“系(研究所、实验室、科室)”共 12 字(14pt ≈ 168pt), +% 塞进 c6-c7(合计 35.90mm ≈ 101.8pt)后,c6-c7 被撑到 126.5pt, +% 整表由 448.3pt 涨到 558.9pt —— 正是那 111.6pt 的 Overfull \hbox。 +% 而【单列】Q[c,m,wd=…] 没有这个问题:内容超出时只溢出、列宽不变 +% (实测在 10.39mm 的 c8 里写 4 个汉字,表宽仍为 448.3pt)。 +% ⇒ 结论:**凡是对齐到合并/窄格里、又必须折行的文字,一律包 \parbox**。 +% 本包为此给每个跨度备了常量与 \khtbfit 包装,见下面 3.2 节。 +%====================================================================== +\newcommand{\khtblwval}{0.5pt} % docx tblBorders sz=4 ⇒ 0.5pt(sz 单位 1/8pt) +\newcommand{\khtbcellmar}{0} % 不再使用内边距,保留名字便于将来调整 + +\newlength{\khtbtblw} +\setlength{\khtbtblw}{158.33mm} % 表宽(含 12 根竖线) + +%---------------------------------------------------------------------- +% 3.1 各列宽(= gridCol − 0.1917mm),单位 mm,四位小数足够。 +% 与 khtbtable 环境里 colspec 的 wd 值必须逐字一致。 +%---------------------------------------------------------------------- +\newcommand{\khtbwa}{18.9661mm} % c1 +\newcommand{\khtbwb}{4.7844mm} % c2 +\newcommand{\khtbwc}{21.3297mm} % c3 +\newcommand{\khtbwd}{18.2605mm} % c4 +\newcommand{\khtbwe}{4.8020mm} % c5 +\newcommand{\khtbwf}{19.2836mm} % c6 +\newcommand{\khtbwg}{16.5848mm} % c7 +\newcommand{\khtbwh}{10.3759mm} % c8 +\newcommand{\khtbwi}{15.1384mm} % c9 +\newcommand{\khtbwj}{1.2037mm} % c10 +\newcommand{\khtbwk}{25.3162mm} % c11(多承担了 0.0198mm 的取整余量) + +%---------------------------------------------------------------------- +% 3.2 各跨度的可用宽(= 所跨各列 wd 之和) +%---------------------------------------------------------------------- +\newcommand{\khtbspanA}{23.7505mm} % c1-c2 职工号 / 单 位 / 政治面貌 +\newcommand{\khtbspanB}{44.3922mm} % c3-c5 单位名(学部 / 学院) +\newcommand{\khtbspanC}{35.8684mm} % c6-c7 系(研究所、实验室、科室) +\newcommand{\khtbspanD}{52.0342mm} % c8-c11 系名 / 学院名 +\newcommand{\khtbspanE}{23.0625mm} % c4-c5 现专业技术职务 +\newcommand{\khtbspanF}{26.7180mm} % c8-c10 所聘岗位 +\newcommand{\khtbspanG}{26.5199mm} % c10-c11 出生年月值 +\newcommand{\khtbspanH}{24.0856mm} % c5-c6 姓名值 / 性别值 + +% 右侧内容栏(c2-c11,跨 10 列)的可用宽 = 十列 wd 之和。 +% ⚠️ 不要再用“实测 \linewidth”得到的那个 379.65pt:它是带竖线、且被 +% xeCJK 行首调整过的结果,换算成 mm 后比真实格宽窄 7mm,会让签字横线 +% 和勾选框提前收尾、右侧留出一大段空白。 +\newcommand{\khtbcellw}{137.0792mm} + +%====================================================================== +% 4. 行高 +% +% 原 docx trHeight + hRule=atLeast(twips → mm): +% R0 412→7.27 R1 460→8.11 R2 939→16.56 +% R3 1261→22.24 R4 1252→22.08 R5 1009→17.80 +% R6 556→ 9.81 R7 1258→22.19 R8 1258→22.19 +% +% ⚠️ tabularray 的 ht= 经实测同为“最小行高”(ht=0pt 与 ht=5mm 同高, +% ht=22mm 才撑开),与 Word 的 atLeast 语义一致 —— 内容多时行会自动 +% 长高,与 Word 表现相同,无需额外处理。 +%====================================================================== + +%====================================================================== +% 5. 表格环境 +% +% ⚠️⚠️ 必须用 longtblr 而不是 tblr: +% 本表内容使总高远超一页可用高度(原 docx 也是 2 页)。而 tblr 是 +% 一整块不可分割的盒子 —— 装进 \setbox 后报 Overfull \vbox (140pt), +% 第 1 页只剩标题、表格整体被推到第 2 页。longtblr 才支持按行断页。 +% +% ⚠️ longtblr 默认会给每页续接处印“表 0: (Continued)”。本表是公文表格, +% 绝不能出现这种字样,故下面用 \DefTblrTemplate 把 +% caption / capcont / conthead-text / contfoot-text 四个模板全部清空。 +% (只写 caption={} 不够,续页标题仍会出来。) +% +% ⚠️⚠️ colspec 与 row{} 必须字面写在这里,不能先存进宏再展开: +% tabularray 的列类型解析在宏展开之外进行,会报 +% “Unexpandable command \xxx inside column type”。 +% (所以上面 3.1 节的 \khtbwa… 只作文档用,不能拼进 colspec。) +% +% ⚠️⚠️⚠️ stretch=0 必须写:longtblr(与 tblr 不同)默认把各列按 \textwidth +% 等比拉伸,实测 11 列 wd 合计 450.46pt 的表被拉成 467.16pt(+16.7pt), +% 表格右边界从 523.7pt 越到 540.4pt,压在页边距外。 +% 加上 stretch=0 后实测宽 448.3pt,与版心严格一致。 +% +% ⚠️⚠️ 【易错点】单元格合并(跨度)全部写死在本环境里,用 +% cell{行}{列}={c=n}{c} +% 声明,而【不要】在数据行里用 \SetCell[c=n]{c}。原因: +% · \SetCell 之后要补若干个空 &,补几个取决于该格跨几列;一旦 +% 某一个数错一位,同行后面所有单元格会整体错列到窄列(如 1.2mm +% 的 c10)里去,报出【每一行都超宽】的 Overfull,从行号上完全 +% 看不出是哪一行错了 —— 这个坑本包踩过。 +% · cell{r}{c}={c=n}{c} 把跨度与数据行分离,每行老老实实写满 +% 11 个单元格,行列对应一目了然。 +% ⚠️ 正确写法只有 {c=n}{c};={c=n}、={n}{c}、={span=n}{c} 都不认。 +% {c=n} 的那个 n 是【列数】,不是“跨度”关键字。 +% 因为本包只服务这一张表,跨度直接写死在下面,.tex 里不用再管。 +% +% docx 各行的 gridSpan(改表时对着数): +% R0 2,1,1,2,1,1,1,2 R1 2,3,2,4 R2 2,1,2,2,3,1 R3~R8 1,10 +% +% ⚠️ 出现在下面选项里的宏名一律不带 @:tabularray 解析选项时 @ 不是 +% 字母,\khtb@lw 会被拆成 \khtb + @lw → Undefined control sequence。 +%====================================================================== +\DefTblrTemplate{caption}{default}{} +\DefTblrTemplate{capcont}{default}{} +\DefTblrTemplate{conthead-text}{default}{} +\DefTblrTemplate{contfoot-text}{default}{} + +\newenvironment{khtbtable}{% + \par\begingroup + \begin{longtblr}[label=none]{ + colspec={ + Q[c,m,wd=18.9661mm] Q[c,m,wd=4.7844mm] Q[c,m,wd=21.3297mm] + Q[c,m,wd=18.2605mm] Q[c,m,wd=4.8020mm] Q[c,m,wd=19.2836mm] + Q[c,m,wd=16.5848mm] Q[c,m,wd=10.3759mm] Q[c,m,wd=15.1384mm] + Q[c,m,wd=1.2037mm] Q[c,m,wd=25.3162mm] + }, + colsep=0pt, rowsep=0pt, stretch=0, + hline{1-Z}={\khtblwval}, vline{1-Z}={\khtblwval}, + row{1}={ht=7.27mm}, row{2}={ht=8.11mm}, row{3}={ht=16.56mm}, + row{4}={ht=22.24mm}, row{5}={ht=22.08mm}, row{6}={ht=17.80mm}, + row{7}={ht=9.81mm}, row{8}={ht=22.19mm}, row{9}={ht=22.19mm}, + %---- R0 职工号|值|姓名|值|性别|值|出生年月|值 + cell{1}{1}={c=2}{c}, cell{1}{5}={c=2}{c}, cell{1}{10}={c=2}{c}, + %---- R1 单位|单位名|系(研究所、实验室、科室)|系名 + cell{2}{1}={c=2}{c}, cell{2}{3}={c=3}{c}, + cell{2}{6}={c=2}{c}, cell{2}{8}={c=4}{c}, + %---- R2 政治面貌|值|现专业技术职务|值|所聘岗位|值 + cell{3}{1}={c=2}{c}, cell{3}{4}={c=2}{c}, + cell{3}{6}={c=2}{c}, cell{3}{8}={c=3}{c}, + %---- R3~R8 竖排标签|内容栏 + cell{4}{2}={c=10}{c}, cell{5}{2}={c=10}{c}, cell{6}{2}={c=10}{c}, + cell{7}{2}={c=10}{c}, cell{8}{2}={c=10}{c}, cell{9}{2}={c=10}{c}, + }% +}{% + \end{longtblr}\par\endgroup} + +%====================================================================== +% 6. 单元格内容包装(见 3 节结论 c 与 d) +% +% 统一入口,.tex 里只用下面三个宏,不要直接把长文字写进 & 之间。 +%====================================================================== +% \khtbfit{跨度宽宏}{内容} —— 定宽、水平居中、可折行 +% 例:\khtbfit{\khtbspanC}{系(研究所、实验室、科室)} +\newcommand{\khtbfit}[2]{\parbox{#1}{\centering #2}} + +% \khtbcell{内容} —— 整条右侧内容栏(c2-c11),垂直居中 +\newcommand{\khtbcell}[1]{\parbox{\khtbcellw}{#1}} +% \khtbcellb{内容} —— 同上,内容贴底(用于签字栏) +\newcommand{\khtbcellb}[1]{\parbox[b]{\khtbcellw}{#1}} + +%====================================================================== +% 7. 竖排栏目标签 +% +% 只有 R3C0 的“年度总结”在 docx 里是【一个字一个段落】显式堆出来的 +% (R3C0 有 16 个 ,“年”“度”“总”“结”各占一段)。 +% 其余窄列标签(R4“系(所、实验室、科室)考评意见”、R5“师德考核结果”、 +% R6“单位年度考核建议档次”、R7“年度考核结果”)在 docx 里都是 +% 【一个普通段落】,靠列窄自然折行,所以包个 \khtbfit 直接写文字即可。 +%====================================================================== +\newcommand{\khtbvert}[1]{% + \begingroup + \khtbbodyfont + \def\khtbvfirst{}% + \@tfor\khtbvch:=#1\do{% + \khtbvfirst\khtbvch\par + \def\khtbvfirst{}}% + \endgroup} + +% \khtbstack{本人,意见} —— 按 docx 的【分段】竖排,每项各占一行 +% R8 首列在 docx 里是 3 个段落(空、“本人”、“意见”),故“本人”和 +% “意见”各成一行;若直接写“本人意见”四字,窄列会折成“本人意/见”, +% 与 Word 不同。 +\newcommand{\khtbstack}[1]{% + \begingroup + \khtbbodyfont + \def\khtbSfirst{}% + \@for\khtbSitem:=#1\do{% + \khtbSfirst\khtbSitem\par + \def\khtbSfirst{}}% + \endgroup} + +%====================================================================== +% 8. 签字 / 日期 / 勾选框 +% +% ⚠️ 这几个宏全部按 \linewidth 定长,因此【必须】放在定宽 \parbox 里用 +% (\khtbcell / \khtbcellb),否则 \linewidth 会等于版心宽而冲出格子。 +% +% ⚠️ 不要用 \hrulefill:它按 \hsize 撑满整行。在 \parbox 里 \hsize 与 +% \linewidth 一致时勉强可用,但本包历史上出过“横线冲出格子、右边界从 +% 522px 涨到 557px”的事故,故一律改用显式长度的 \rule。 +%====================================================================== + +% 签字行:标签 + 一条一直画到行末的横线 +% \khtbsign{本人签名:} +% +% ⚠️ 参数是【必选】的,不要写成 \newcommand{\khtbsign}[1][默认]{...}。 +% 那样调用 \khtbsign{负责人签名:} 时,{...} 不是可选参数形式 [...] +% 而不会被吃掉,结果是:先印出默认的“本人签名:”,随后那个参数组 +% 在 \par 之后再单独排成一行 —— 一格里凭空多出两行签字,且标签还是错的。 +% 本包踩过这个坑:全文“本人签名”出现了 4 次。 +\newbox\khtbsignbox +\newcommand{\khtbsign}[1]{% + \par\noindent + \sbox\khtbsignbox{#1}% + \usebox\khtbsignbox + \raisebox{-0.4ex}{\rule{\dimexpr\linewidth-\wd\khtbsignbox\relax}{0.4pt}}% + \par} + +% 日期行:年 / 月 / 日 靠右,中间留手写空隙 +\newcommand{\khtbdate}{% + \par\noindent + \makebox[\linewidth][r]{年\hspace{1.6em}月\hspace{1.6em}日}% + \par} + +% 填空横线:\khtbunderline{6em} ⇒ 一条 6em 长的横线 +% docx 里“考核结果为____”处是若干带 w:u 的空格,这里换成规则横线。 +% ⚠️ 横线长度必须用参数 #1,不能写 \linewidth —— makebox 内部 \linewidth +% 并未改变,仍是外层 parbox 的宽度(389pt),会画出一条贯穿整栏的线。 +\newcommand{\khtbunderline}[1]{% + \makebox[#1][c]{\rule[-0.4ex]{#1}{0.4pt}}} + +% 档次勾选框:每项前一个空心方框 +% \khtbchoices{优秀,合格,基本合格,不合格} +% +% ⚠️ 项间用 \hss 做弹性间距,而不是固定 \hspace{1.5em}: +% 5 项(优秀/合格/基本合格/不合格/不确定档次)在 14pt 下按固定 1.5em +% 排要 395pt,超过右侧内容栏的 389pt,会把整张表撑宽。 +% 用 \hbox to\linewidth + 5 个 \hss(首、尾、中间 3 处等分), +% 剩余空间自动均分,总宽永不超过栏宽。 +% +% ⚠️ 原 docx 用 Wingdings 的 ¨(char 0x00A8)画未勾选的方框。 +% 这里改用 U+25A1 “□”:实测仿宋、黑体都有该字形,宋体没有, +% 故正文默认仿宋;若把正文改成宋体,需另指定方框字体。 +\newcommand{\khtbchoices}[1]{% + \par + \begingroup + \khtbbodyfont + \noindent + \hbox to\linewidth{% + \hss + \def\khtbsep{\hss}% + \def\khtbfirst{}% + \@for\khtbit:=#1\do{% + \khtbfirst\mbox{□\,\khtbit}% + \def\khtbfirst{\khtbsep}}% + \hss}% + \par + \endgroup} + +% 单位负责人签字 + 公章 + 日期:三行(docx 首行缩进 2 字) +\newcommand{\khtbseal}[1][2\ccwd]{% + \par\noindent\hspace*{#1}单位负责人签字:\par + \noindent\hspace*{#1}(公章):\par + \noindent\hspace*{#1}年\hspace{1.6em}月\hspace{1.6em}日\par} + +%====================================================================== +% 9. 表外标题 +% +% 原 docx 第 1 段:黑体 22pt、居中、行距 exact 480twips=24pt、字距 -0.7pt +% 原 docx 第 2 段:仿宋 16pt。docx 里是 firstLine 640twips(2 字)缩进 +% 且未设 jc,实际渲染为“左缩两字”而非居中 —— 更像原表排版的疏漏。 +% 本模板改为居中(更符合版式意图);若要还原原样,把下面 \centering +% 换成 \hspace*{2\ccwd} 即可。 +%====================================================================== +\newcommand{\khtbyearval}{××××} +\newcommand{\khtbyear}[1]{\renewcommand{\khtbyearval}{#1}} + +\newcommand{\khtbtitle}{% + \begingroup + \centering + {\heiti\fontsize{22}{24}\selectfont + \addfontfeature{LetterSpace=-3.2}% + 中国海洋大学教职工年度考核登记表\par}% + \vspace{2pt}% + {\fangsong\fontsize{16}{20}\selectfont \khtbyearval\,年度\par}% + \endgroup + \vspace{5pt}} + +%====================================================================== +% 10. 表外脚注 +% +% 原 docx 第 4 段:仿宋 14pt、居中 +% 内容“注:此表存入本人档案(A4纸正反面打印) 人事处制表” +%====================================================================== +\newcommand{\khtbfootnote}{% + \par\vspace{2pt}% + {\khtbbodyfont + \noindent\makebox[\linewidth][c]{% + 注:此表存入本人档案(A4 纸正反面打印)\quad 人事处制表}\par}} + +%====================================================================== +% 11. 年度总结正文区 +% +% \khtbsummary{正文} 多段用 \par 或空行分隔;首行缩进 2 字 +% \khtbsummarysign 末尾“本人签名 / 年 月 日”(docx 缩进 13 字) +%====================================================================== +\newcommand{\khtbsummary}[1]{% + \begingroup + \khtbbodyfont + \setlength{\parindent}{2\ccwd}% + \setlength{\parskip}{0pt}% + #1\par + \endgroup} + +\newcommand{\khtbsummarysign}{% + \par\vspace{1.5em}% + \begingroup + \setlength{\parindent}{0pt}% + \noindent\hspace*{13\ccwd}% + \sbox\khtbsignbox{本人签名:}% + \usebox\khtbsignbox + \raisebox{-0.4ex}% + {\rule{\dimexpr\linewidth-13\ccwd-\wd\khtbsignbox\relax}{0.4pt}}% + \par + \vspace{0.2em}% + \noindent\hspace*{13\ccwd}年\hspace{1.6em}月\hspace{1.6em}日\par + \endgroup} + +\AtBeginDocument{\khtbbodyfont} +\endinput \ No newline at end of file diff --git a/form/年度考核登记表.pdf b/form/年度考核登记表.pdf new file mode 100644 index 0000000..d59c78d Binary files /dev/null and b/form/年度考核登记表.pdf differ diff --git a/form/年度考核登记表.tex b/form/年度考核登记表.tex new file mode 100644 index 0000000..6457f3e --- /dev/null +++ b/form/年度考核登记表.tex @@ -0,0 +1,125 @@ +%====================================================================== +% 中国海洋大学 教职工年度考核登记表 +% +% 编译: xelatex 年度考核登记表.tex +% (跑两遍,第二遍才取到正确页码) +% +% 本文件刻意不含真人信息:姓名/职工号/出生年月/单位/岗位等一律用 +% × 占位。填表时只改下面【第 1 节 基本信息】和【第 3 节 年度总结】。 +% +% 版式来源:2025 年学校下发的 Word 表(A4、表宽 158.33mm、11 列、 +% 仿宋 14pt)。所有尺寸已在 ouckhtb.sty 内注明换算过程; +% 要改版式请改 sty,不要在这里加 \vspace 硬撑。 +%====================================================================== +\documentclass[UTF8,fontset=none]{ctexart} +\usepackage{ouckhtb} + +%====================================================================== +% 1. 基本信息(填表时只改这一段) +%====================================================================== +\khtbyear{2025} + +\newcommand{\khnum}{0000000} % 职工号 +% ⚠️ 占位符“×”必须包 \fangsong:它会被 fontspec 当成 ASCII 交给 +% Times New Roman,而 TNR 的 × 是 1em 宽的数学符号(14pt 一格), +% 9 个就是 126pt,撑破所在列。用仿宋(全角)宽度才与汉字一致。 +\newcommand{\khname}{{\fangsong ××}} % 姓名(2 字宽) +\newcommand{\khsex}{{\fangsong ×}} % 性别 +\newcommand{\khbirth}{{\fangsong ××××.××}} % 出生年月 +\newcommand{\khdept}{{\fangsong ××××××××}} % 单位(学部/学院) +\newcommand{\khsubdept}{{\fangsong ××××××××}} % 系(研究所、实验室、科室) +\newcommand{\khparty}{{\fangsong ××××}} % 政治面貌 +\newcommand{\khtitle}{{\fangsong ×××}} % 现专业技术职务 +\newcommand{\khpost}{{\fangsong ×××}} % 所聘岗位 + +% 年度总结正文。多段之间用 \par 分隔。 +\newcommand{\khsummary}{% + 本人在思想上始终积极要求进步,……(此处填写年度思想政治表现)。\par + 在教学工作中,本年度承担××××等课程的教学任务,……(教学工作情况)。\par + 在科研方面,……(科研与项目情况)。\par + 在人才培养方面,……(人才培养与团队建设情况)。} + +%====================================================================== +% 2. 表外标题 +%====================================================================== +\begin{document} +\khtbtitle + +%====================================================================== +% 3. 表格主体 +% +% ⚠️⚠️ 每个单元格都要写满,跨度不用管(已写死在 ouckhtb.sty 里): +% 本表 11 个网格列、9 行,每行都老老实实写 11 个格子 + 结尾 \\ +% 跨列合并由 sty 的 cell{r}{c}={c=n}{c} 声明,若某格是合并的起点, +% 它后面应补 (n−1) 个空 & ,凑满 11 格。数错一位就会整体错列。 +% +% ⚠️⚠️⚠️ 合并格里的文字【必须】用 \khtbfit{跨度宽宏}{文字} 包起来。 +% 因为 cell{r}{c}={c=n}{c} 的 {c} 是【不折行的 LR 模式】: +% 文字比所跨各列合计更宽时,它不会折行,而是把列撑宽、整张表超出版心 +% (实测“系(研究所、实验室、科室)”把表从 448.3pt 撑到 558.9pt)。 +% 单列的 Q[c,m,wd=…] 没有这个问题,所以只有合并格需要包。 +%====================================================================== +\begin{khtbtable} + +%---- R0 职工号 / 姓名 / 性别 / 出生年月 ------------------------------- +职工号 & & \khnum + & 姓名 & \khtbfit{\khtbspanH}{\khname} & & + & 性别 & \khsex + & 出生年月 & \khtbfit{\khtbspanG}{\khbirth} & \\ + +%---- R1 单位 / 系(研究所、实验室、科室) ---------------------------- +\khtbfit{\khtbspanA}{单\hspace{1em}位} & & + \khtbfit{\khtbspanB}{\khdept} & & & + \khtbfit{\khtbspanC}{\khtbxi} & & + & \khtbfit{\khtbspanD}{\khsubdept} & & & \\ + +%---- R2 政治面貌 / 现专业技术职务 / 所聘岗位 ------------------------- +\khtbfit{\khtbspanA}{政治面貌} & & \khparty + & \khtbfit{\khtbspanE}{现专业技术职务} & & \khtitle + & & \khtbfit{\khtbspanF}{所聘岗位} & & & \khpost \\ + +%---- R3 年度总结(竖排标签 + 正文栏) ------------------------------- +% 正文与签名写进一个固定宽的 \parbox,否则会按版心宽折行冲出格子。 +\khtbvert{年度总结} + & \khtbcell{\khtbsummary{\khsummary}\khtbsummarysign} + & & & & & & & & & \\ + +%---- R4 系(所、实验室、科室)考评意见 ------------------------------- +\khtbfit{\khtbwa}{系(所、实验室、科室)考评意见} + & \khtbcellb{\khtbsign{负责人签名:}\khtbdate} + & & & & & & & & & \\ + +%---- R5 师德考核结果 ------------------------------------------------ +\khtbfit{\khtbwa}{师德考核结果} + & \khtbcell{\khtbchoices{优秀,合格,基本合格,不合格}\khtbseal} + & & & & & & & & & \\ + +%---- R6 单位年度考核建议档次 ---------------------------------------- +\khtbfit{\khtbwa}{单位年度考核建议档次} + & \khtbcell{\khtbsmallnote + (对考核档次为基本合格、不合格、不确定档次的人员需说明原因)\par + \khtbbodyfont + \khtbchoices{优秀,合格,基本合格,不合格,不确定档次}\khtbseal} + & & & & & & & & & \\ + +%---- R7 年度考核结果 ------------------------------------------------ +\khtbfit{\khtbwa}{年度考核结果} + & \khtbcell{\khtbchoices{优秀,合格,基本合格,不合格,不确定档次}\khtbseal} + & & & & & & & & & \\ + +%---- R8 本人意见 ---------------------------------------------------- +% docx 里首列是 3 个段落(空 / “本人” / “意见”),故两词各占一行。 +\khtbstack{本人,意见} + & \khtbcell{本人知晓并同意考核结果为\khtbunderline{6em}。\par + \vspace*{0.4em}% + \khtbsign{本人签名:}\khtbdate} + & & & & & & & & & \\ + +\end{khtbtable} + +%====================================================================== +% 4. 表外脚注 +%====================================================================== +\khtbfootnote + +\end{document} \ No newline at end of file