LaTeX 模板调试实战:从封面分页到目录全崩的排错之旅
2025-6-3
| 2025-6-3
字数 1984阅读时长 5 分钟

LaTeX 模板调试实战:从封面分页到目录全崩的排错之旅

 
标签: LaTeX, XeLaTeX, 模板调试, 排版, 封面, 目录, tocloft

前言

最近,为了完成一份课程设计报告,我用上了一份学校流传下来的 LaTeX 模板。本以为能直接套用,享受 LaTeX 带来的高效与优雅,没想到却开启了一段曲折离奇的“排错之旅”。从封面上的日期“离家出走”,到目录格式的“彻底放飞”,再到宏包之间的“神仙打架”,几乎每个环节都给我带来了“惊喜”。
这篇博文旨在记录我解决这一系列问题的全过程,分享每一步的分析思路和最终的解决方案。希望这份“血泪史”能为将来遇到类似问题的你,提供一份可供参考的调试指南。

第一站:离家出走的封面日期

症状:
一切从封面开始。当我填好所有信息并编译后,发现一个奇怪的现象:报告的标题、姓名、学号等信息在第一页,而最下方的学校名称和日期,却被无情地推到了第二页。
分析与解决:
这通常是由于页面垂直空间不足导致的。最开始,在无法查看模板源码 (config.tex) 的情况下,我尝试了一个“简单粗暴”的急救方法:在 \date{} 命令里加入一个负的垂直间距 \vspace{-5cm},强行把日期“拉”回来。
这个方法虽然奏效,但治标不治本。拿到 config.tex 的源码后,真相大白:原作者在 \renewcommand{\maketitle} 中使用了多个固定的 \vspace{Xem} 来控制间距。当内容稍多或屏幕尺寸变化时,这些固定间距的总和就超出了单页限制。
最终方案:
修改 config.tex 中的 \renewcommand{\maketitle} 定义,将所有固定的 \vspace 命令替换为弹性的 \vfill 命令。\vfill 能自动计算并分配页面上所有可用的垂直空白,从而保证无论内容多少,所有元素都能优雅地分布在同一页内,永不分页。
Code snippet
% 在 config.tex 中 \renewcommand{\maketitle}{ \begin{titlepage} \begin{center} % ... 标志等内容 ... \vfill % 使用弹性间距 % ... 标题等内容 ... \vfill % 使用弹性间距 % ... 作者信息表格 ... \vfill % 使用弹性间距 % ... 日期 ... \end{center} \end{titlepage} }

第二站:混乱的目录(上)- 格式对不齐

症状:
解决了封面问题后,目录又给了我一击。生成的目录中,各级标题的编号和文本完全没有对齐,缩进混乱,毫无美感可言。
分析与解决:
检查 config.tex 发现,模板作者为了自定义目录样式,使用了 titletoc 宏包的 \titlecontents 命令。然而,其中的参数设置得非常复杂且相互冲突,比如一级标题和二级标题的左边距被设成了相同的值,这直接导致了视觉上的混乱。
最终方案:
“大扫除”开始。既然模板已经加载了另一个更强大且语法更简洁的目录宏包 tocloft,最简单的办法就是彻底放弃 titletoc。
  1. config.tex 中,注释掉 \usepackage{titletoc}
  1. 删除所有复杂的 \titlecontents 命令。
  1. 改用 tocloft 提供的专用命令,重新精确定义每一级标题的缩进 (indent) 和编号宽度 (numwidth)。
Code snippet
% 在 config.tex 中 \usepackage{tocloft} % 确保使用 tocloft % 删除所有 \titlecontents 命令... % 使用 tocloft 的命令进行设置 \setlength{\cftsecindent}{0em} \setlength{\cftsecnumwidth}{2.5em} \setlength{\cftsubsecindent}{2.5em} \setlength{\cftsubsecnumwidth}{3em} \setlength{\cftsubsubsectionindent}{5.5em} \setlength{\cftsubsubsecnumwidth}{3.5em} % ...
这套命令逻辑清晰,下一级的缩进等于上一级的缩进加上上一级的编号宽度,保证了完美的对齐。

第三站:混乱的目录(下)- 无法分页

症状:
当目录内容超过一页时,它并没有像预期的那样自动生成第二页,而是“溢出”到了页面底部,甚至覆盖了下一页正文的页眉。
分析与解决:
这个问题非常典型,通常意味着整个目录被装进了一个“不可分页”的盒子里。经过排查,罪魁祸首是 config.tex 中的一行代码:
\renewcommand{\contentsname}{\centerline{...}}
\centerline 是一个比较底层的 TeX 命令,它的副作用就是会将其中的内容视为一个不可打断的整体,这个“不可打断”的属性意外地污染了整个目录环境。
最终方案:
放弃这个陈旧的命令,改用 tocloft 宏包的官方推荐方式来定义目录标题的样式,做到内容与样式的分离。
  1. \renewcommand{\contentsname}{...} 只定义标题的文字
  1. tocloft 的专用命令 \cfttoctitlefont\cftaftertoctitle 来定义标题的样式(字体、大小、对齐)。
Code snippet
% 在 config.tex 中 % 1. 只定义内容 \renewcommand{\contentsname}{目\hspace{2em}录} % 2. 用专用命令定义样式 \renewcommand{\cfttoctitlefont}{\hfill\hei\bfseries\erhao} \renewcommand{\cftaftertoctitle}{\hfill}
这种方法更稳定,也更符合现代 LaTeX 的编程思想,彻底解决了分页问题。

第四站:最后的微调与“缓存”疑云

症状:
在解决了所有大问题后,我想把目录标题的字号调得更大一些。我明明在 config.tex 中把字号命令从 \erhao 改成了 \xiaochuhao,但无论怎么编译,PDF 中的字号就是不变。
分析与解决:
我首先怀疑是 LaTeX 的缓存问题。LaTeX 在编译时会生成 .toc, .aux 等辅助文件,有时修改格式后,需要彻底清除缓存才能让修改生效。在 Overleaf 等在线平台,通常在“重新编译”按钮旁边有一个“清除缓存文件”的选项。
然而,在更换编译平台后问题依旧,证明这次不是缓存的锅。这迫使我重新审视代码,最终确定是 \renewcommand{\contentsname} 的格式化方式与 ctex 宏包的内部机制存在深层冲突。这再次印证了第三站中采用 tocloft 专用命令是多么重要。
在采用了第三站的最终方案后,调整字号的命令立刻就生效了。

总结与感悟

这次看似简单的排版任务,最终演变成了一场涉及宏包冲突、底层命令副作用和缓存机制的综合调试。回过头看,我学到了几点宝贵的经验:
  1. 魔鬼在细节中: 一个不经意的陈旧命令(如 \centerline)可能会引发全局性的灾难。
  1. 尊重宏包的“API”: 尽量使用宏包作者提供的专用命令(如 tocloft\cft... 系列)来进行定制,而不是用通用命令去“硬掰”,这样能最大程度地避免冲突。
  1. 内容与样式分离: 这是一个优秀的设计思想,它让代码更清晰,也更容易维护和调试。
  1. 先清缓存再思考: 当遇到“改了但没生效”的灵异事件时,首先应该清理缓存再编译,这能排除掉至少50%的问题。
虽然过程曲折,但最终完美解决所有问题后的成就感是无与伦比的。希望这篇“踩坑”记录,能让你在 LaTeX 的道路上走得更顺一些。
  • LaTeX
  • XeLaTeX
  • 模板调试
  • 推荐
  • 思考
  • 工具
  • 排版
  • 封面
  • tocloft
  • 探秘纠错码的“瑞士军刀”:RS码从入门到原理九千九百九十九
    Loading...