Files
ouc_latex_template/课程执行大纲/README.md
T
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

12 KiB
Raw Blame History

课程执行大纲 —— 本科课程教学执行大纲、教学日历(LaTeX 模板)

中国海洋大学下发的《本科课程教学执行大纲》Word 模板的 XeLaTeX 复刻版。 内容全部虚构(课程名、课程代码、开课号、教师、教材、思政案例),只复刻版式。

样张是一份填完整的虚构大纲:《信号与系统基础》2026 秋、电子信息工程专业、 56 课时 3.0 学分(含 18 实践学时)、开课号 99663311、任课教师「陈立群」、 教材用吴大正《信号与线性系统分析》(高等教育出版社)、参考书用郑君里那本。

注意本模板刻意不套用其他模板的「数字逻辑 / 张远航」那套设定 —— 这份大纲原作就是《信号与线性系统分析》的课,强行改成数字逻辑, 大纲里的章节体系、学时分配、思政案例就全对不上了。虚构也要虚构得自洽。

文件 说明
课程执行大纲.tex 主文件。虚构课程的一份完整示例
ouccourse.sty 版式宏包。尺寸全部从原 docx 的 OOXML 量出
课程执行大纲.pdf 编译产物,5 页(与原 docx 一致)

编译

xelatex 课程执行大纲.tex        # 单次即可,无交叉引用

需要 ctex + geometry + fontspec + xeCJK + tabularray。 实测环境:TeX Live 2022 / tabularray 2022A。

换成一门真实的课

只改 课程执行大纲.tex 顶部的宏定义,不要动 ouccourse.sty。

\newcommand{\cfcourse}{信号与系统基础}      % 课程名
\newcommand{\cfyear}{2026}                  % 学年
\newcommand{\cfseason}{秋}                  % 季学期
\newcommand{\cfmode}{考试}                  % 考核方式:考试/考查/论文
\newcommand{\cfcode}{081203304517}          % 课程代码
\newcommand{\cfhour}{56}                    % 总课时
\newcommand{\cfcredit}{3.0}                 % 学分
\newcommand{\cfprac}{18}                    % 实践学时
\newcommand{\cfteacher}{陈立群}              % 任课教师
\newcommand{\cfteachno}{99663311}           % 开课号
\newcommand{\cfmajor}{电子信息工程}          % 面向专业
\newcommand{\cfattr}{专业核心必修课}         % 课程属性

正文各节直接用 \ccsec{}(一级标题)、\ccp{}(带 2 字首行缩进的正文)。

表 0 —— 成绩综合评分体系

\begin{ccscoretable}
成绩综合评分体系 & 比例\% \\      % 表头
1.课下作业、课堂讨论及平常表现 & 24 \\
2.实验成绩 & 20 \\
3.期末考试成绩 & 56 \\
总计 & 100 \\
\end{ccscoretable}

行数可以增减,行高自动(每行 7.834mm)。

表 1 —— 教学日历

\begin{cctable}
{\ccfang\ccszxi\bfseries 周次} & ... & {\ccszix 内容} & 2 & {\ccszix ...} & {\ccszix ...} \\
\end{cctable}
  • 6 列,顺序固定:周次 / 内容顺序 / 主题 / 计划课时 / 教学内容及教学方式 / 思政点及支撑指标点情况
  • 纵向合并周次段用 \SetCell[r=2]{c}(跨 2 行,r=N 即跨 N 行)
  • 表尾「合计」行后有两个 \SetCell[c=6]{c} 的整行合并(任课老师签字 / 审核意见)
  • 表内默认 9pt;表头用 \ccszxi(11pt)加粗;审核意见格内部钉死 10.5pt/12.6pt

版式数据来源(twips → mm)

原 docx 的 sectPr:

属性 twips mm 说明
pgSz w 11910 210.08 WPS 存的"非标准 A4",本包用标准 210
pgSz h 16840 297.04 同上,用 297
pgMar top 1420 25.05 上边距
pgMar bottom 280 4.94 下边距极小,原文件为塞进 5 页压出来的
pgMar left 1560 27.52 左边距
pgMar right 1300 22.93 右边距(左右不对称,照抄)
pgMar header/footer 720 12.70 无页眉页脚内容,仅占位

换算:mm = twips / 1440 × 25.4,pt = twips / 20。

表 0(成绩综合评分体系)

项目 twips mm
gridCol 7479 + 1418 131.921 + 25.012
表宽 8897 156.93
tblCellMar left/right 108 1.905
trHeight(exact) 454 8.01(本包用 7.834,见坑 3)
边框 sz 4 0.5pt

tblLayout fixed、jc center、tblW 0 auto。全表 12pt 仿宋(朱雀仿宋)。

表 1(教学日历)

项目 twips mm
gridCol 846,1134,1877,850,2835,1843 14.922, 20.002, 33.108, 14.993, 50.006, 32.508
表宽 9385 165.54(超版心 5.91)
trHeight R0(atLeast) 917 16.17
trHeight R14(atLeast) 1825 32.19
trHeight R15(atLeast) 1073 18.93(只是下限,实际被撑到 56mm)

16 行。R1~R13 无 trHeight,行高由内容决定。纵向合并 5 组(R1-R2、R3-R4、 R5-R6、R7-R8、R9-R10);R14/R15 是 gridSpan=6 的整行合并。

六个必须知道的坑

1. 表宽 > 版心时,不要缩放列宽

docx 里表 1 是 165.54mm,版心只有 159.55mm。Word 允许表格超出、居中后压进左右页边距。

不要按 159.55/165.54 按比例缩列宽。 缩了之后长文字会提前折行,行高、页数全变。 正确做法:列宽照抄 gridCol,用 \leftskip 把整块左移。

\hsize=\cctblw \linewidth=\cctblw      % 让表内得下,不报 Overfull
\leftskip=-\cctblshift \rightskip=0pt   % 整块左移 5.29mm,落到 22.23mm

\hspace* 对 longtblr 生成的 \halign 盒子无效,会被吞掉,必须用 \leftskip。

2. wd= 是内容宽,不含竖线自身的宽度

tabularray 的 Q[...,wd=X] 里 X 是内容宽。每条 vline 自身还占 0.5pt = 0.17639mm。

表 1:6 列 7 条线,每列承担 7/6 条 ⇒ wd = gridCol − 2×colsep − 0.2058
表 0:2 列 3 条线,每列承担 1.5 条 ⇒ wd = gridCol − 2×colsep − 0.2646

漏算的后果很隐蔽:表看起来对,但总宽每列多 0.18mm,6 列就差出 1mm。

3. ht= 也含横线宽度预算

row{1-Z}={ht=8.01mm} 画出来是 8.19mm(每行多一条 0.5pt 横线)。 要得到 8.01mm 的真实行高,ht 要给 7.834mm。

4. presep/postsep/headsep/footsep 是 outer 键

写进 \begin{longtblr}[...] 的方括号里;写进花括号(inner spec)不会生效, 反而会把 0pt 当表内容印在表格第一行 —— 表头上会出现一串 0pt0pt0pt0pt 的垃圾文字,而且不报错。

同理,表级默认字号必须写 cells={font=\ccszix},单独写 font= 会被静默忽略。

5. 跨页续页提示要清两组模板

longtblr 跨页时默认印 ( Continued )、表尾印 Continued on next page, 有 caption 时还印 表0:。清干净要动两组:

% (a) 内容模板 *-text —— 不能设成 empty!会报
%     "LaTeX3 Error: Erroneous variable \l__tblr_template_conthead_text_tl"
\DefTblrTemplate{conthead-text}{normal}{}
\DefTblrTemplate{contfoot-text}{normal}{}
\SetTblrTemplate{conthead-text}{normal}
\SetTblrTemplate{contfoot-text}{normal}
% (b) 模板实例
\SetTblrTemplate{caption-tag}{empty}
\SetTblrTemplate{caption-sep}{empty}
\SetTblrTemplate{caption-text}{empty}
\SetTblrTemplate{caption}{empty}
\SetTblrTemplate{conthead}{empty}
\SetTblrTemplate{contfoot}{empty}

只做 (b) 时第 5 页仍会出现「表0:」与「(Continued)」,因为模板实例里调的是 \UseTblrTemplate{...}{default},会回退到 normal 内容。

6. \linespread 是乘在基准字号上的

ctex 默认 \linespread ≈ 1.3,会把 \fontsize{12}{18} 的行距放大到 23.4pt。

给字号设行距时必须先归 1:

\newcommand{\ccfont}[2]{\linespread{1}\relax\fontsize{#1}{#2}\selectfont}

反过来,在已经缩小过字号的上下文里,不能用 \linespread{1.2} 当"1.2 倍行距" (它乘的是外层的 9pt,不是当前的 10.5pt),要直接钉 \fontsize{10.5}{12.6}。

字体

原 docx 用了 4 个字体,其中 3 个是方正商业字体,嵌在 docx 里但本机没装。 旧版做法是降级到 Windows 自带字体(宋体/黑体/仿宋 + AutoFakeBold 伪粗), 但这既依赖本机装了什么字体(换台机器就可能编不出),而且 SimSun / SimHei / FangSong 也都不允许随仓库分发。

现在全部改用仓库公共字体包 ../fonts.tex:

docx 原字体 用在哪 本包替代 命令
方正小标宋简体 校名、副标题、大标题、教学日历 OUC Serif 真粗体 \ccbiaosong
方正仿宋_GB2312 正文、表 0、签字栏 朱雀仿宋 \ccfang
黑体 各级标题 OUC Sans(思源黑体) \cchei
宋体 教学日历表 9pt OUC Serif(思源宋体) \ccsong

比原来的伪粗更好:小标宋本来就是宋体的标题变体,用思源宋体自带的真粗体, 笔画不会像 AutoFakeBold=3.2 那样糊在一起。

⚠️ 朱雀仿宋只有常规一档,\ccfang 下 \bfseries 不会真的变粗。 教学日历表头(课程执行大纲.tex 里的 {\ccfang\ccszxi\bfseries 周次} 等 6 处) 原来靠 AutoFakeBold=2.5 伪粗,现在给 ccfang 单独开了 FakeBold=0.8 保住层次(见 ouccourse.sty 的注释)。若要更实在的粗体,把那几处 \ccfang 换成 \cchei —— 黑体本身就是标题用的重字面。

同时 \xeCJKsetup{CJKecglue={}} 关掉了西文与汉字之间的自动空隙 —— 原 docx 没有这种空隙, 不关会出现「×× 学部×× 学院」这种多出来的空格。

与 docx 的已知差异

项目 docx 本模板 原因
纸张 210.08 × 297.04 210 × 297 标准 A4,肉眼不可辨
表格是否跨页 表 1 跨第 4/5 页 同 表高 334mm > 版心 267mm
跨页处表头 不重复(无 tblHeader) 不重复 一致
行内是否允许断开 允许(无 cantSplit) 允许 一致
表 0 每行高 8.01 8.01 一致
表 1 表宽 165.54 165.36(−0.18) 竖线宽度舍入
字体 方正小标宋/仿宋 思源宋体粗/朱雀仿宋 商业字体不可分发,已换开源替代
修订标记 46 处 w:ins 不保留 已接受全部插入修订
46 处 w:ins 中的红字 color=C00000 黑色 那是修订高亮,非正式版式

校验方法

不靠肉眼,靠量。

pdftocairo -svg -f 4 -l 4 课程执行大纲.pdf /tmp/p4.svg   # 矢量线条
pdftotext -bbox 课程执行大纲.pdf /tmp/bbox.html           # 字坐标

或用 pymupdf 直接读(推荐,能同时拿到线段与 span 的 bbox):

import pymupdf
d = pymupdf.open('课程执行大纲.pdf')
for dr in d[3].get_drawings():          # 表格横竖线
    for it in dr['items']:
        if it[0] == 'l':
            print(it[1], it[2])         # 两端点,单位 pt

注意:同一条竖线会被重复计入多次(每个单元格一段),做列宽计算前必须 sorted(set(round(x,2) ...)) 去重,否则 xs[1]-xs[0] 算出来是 0。

验收结果(实测,26/26 项达标)

表 0   宽 156.753  目标 156.930  差 −0.177
       左  27.608  目标  27.520
       高  40.040  目标  40.050
       列  131.830 / 24.924  目标 131.921 / 25.012
表 1   宽 165.358  目标 165.540  差 −0.182
       左  22.320  目标  22.270
       列  14.894 / 19.971 / 33.076 / 14.965 / 49.975 / 32.477
           目标 14.922 / 20.002 / 33.108 / 14.993 / 50.006 / 32.508
       R0 16.334(目标 16.170)  R14 32.385(目标 32.190)
       R15 56.339(atLeast 下限 18.930,被 12 段内容撑高)
页数   5(与原 docx 一致)
编译   零错误、零 Overfull、零 Underfull
各页最低点均 ≤ 292.06mm 版心下沿,无越界