Files
ouc_latex_template/课程大纲/oucSyllabus.sty
T
laoyang dc5e9337e8 新增《本科生课程大纲》LaTeX 模板 #23
源文件:SynologyDrive\授课\数字逻辑\教学大纲\课程大纲模板-数字逻辑-2024版.docx
(2025-01-02 修订,是同目录 17 个文件里最新的一个)。所有尺寸从 OOXML 量出。

## 新增文件

   课程大纲/oucSyllabus.sty   版式包
   课程大纲/课程大纲.tex      示例(数字逻辑,已脱敏)
   课程大纲/README.md         用法

## 版式参数(实测)

   页面    A4 210×297mm
   边距    上下左右均 25.4mm(正好 1 英寸)
   正文    12pt      大标题 15pt 居中      表格 9~10pt
   原 docx 字体:Times/宋体/黑体/仿宋_GB2312/微软雅黑

字体全部取自 ../fonts.tex(OUC Serif + OUC Sans),无系统字体依赖。
仿宋_GB2312 与微软雅黑是商业字体,不能随仓库分发(#17 的规矩)。

## 还原的 6 个表格

   表0  课程基本信息   6 行,不规则(各行列跨度不同)
   表1  课程目标×指标点  6×6 打勾矩阵
   表2  目标×教学内容    6×3
   表3  教学进度         8×5(主要大表)
   表4  成绩与能力对应   6×4
   表5  成绩评分体系     5×2

## 踩坑记录(都写进代码注释了)

### 1. tabularray 的 \SetCell 会吞掉下一格,且不报错

`\SetCell[c=2]{c} 内容 & 下一格` → **下一格连同内容一起消失**。

最小复现(6 列表):
    A & \SetCell[c=2]{c} B & C & \SetCell[c=2]{c} D \\
渲染只得 A / B / D,C 没了。**没有报错,没有任何警告。**

✅ 正确写法:跨 n 列后用 n-1 个 `{}` 占位
    A & \SetCell[c=2]{c} B & {} & C & \SetCell[c=2]{c} D & {} \\

⇒ 规律:`&` 总数固定为「列数-1」,与是否跨列无关。
   跨列只是把内容摊到多格上,被摊掉的格要用 `{}` 顶住。

这个坑让「责任教师」「课程性质」「总课时」三个标签凭空消失了三轮,
每次都要靠 pymupdf 逐行数文字才发现。README 里也记了。

### 2. xeCJK 带缩进的段落会多排一个字,但也不报 Overfull

A4、左右 25.4mm、\linewidth=452.97pt、版心右界 523.28bp 下实测:

    无缩进的纯中文段落     右缘 523.28  ✅
    带 2em 缩进(三种写法) 右缘 530.53  ❌ 超 7.25bp

三种失败的写法:
    ① \par\noindent\hspace*{2em}#1\par
    ② \par\setlength{\parindent}{2em}\indent #1\par
    ③ \parbox{\linewidth}{\setlength{\parindent}{2em}\indent #1}

根因:xeCJK 算断行点时仍按「整行可用宽度」,比应停的位置多放一个字。

✅ 正解:把 \hsize 也减掉缩进量
    \setlength{\hsize}{\dimexpr\linewidth-2em\relax}
    \setlength{\parindent}{2em}
实测右缘 502.28bp,落在版心内。

⚠️ 同样**不报 Overfull** —— TeX 认为这行"刚好"。

### 3. 表 0 列宽不能用固定值

课程代码「080502101231」12 位数字,10.5pt 下宽约 22mm + 内边距 3.81mm。
标签列 26.5mm → Overfull 10.26pt;24mm → 3.14pt;22mm → 0。
22mm 是下限(再窄「课程名称」自己折行)。

## 验证

全库 14/14 通过(新增第 14 项,已加入 verify_all.sh TARGETS):

   课程大纲  6 页  err=0 over=0

逐页越界检查:6 页最右 499.37~514.48bp,全部在版心 523.3bp 内。
内容核查:标题、12 项基本信息、八章标题、7 个关键段落、签字栏,
共 17 项全部命中。

双端一致:
   WSL TeX Live 2025    6 页 err=0 over=0
   Windows TeX Live 2022 6 页 err=0 over=0

## 偏离原文件的地方(README 有表)

1. 「六、成绩评定」原 docx 是 10.5pt,与其余七章 12pt 不一致
   (复制粘贴漏改),本模板统一 12pt。
2. 表 0 的竖线按 6 等分统一,原 docx 逐行不同(tabularray 限制)。

## 脱敏

责任教师等真实姓名换成虚构的「张远航」,与仓库其他模板一致。
2026-10-30 13:45:19 +08:00

287 lines
13 KiB
TeX
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
%======================================================================
% oucSyllabus.sty —— 中国海洋大学 本科生课程大纲 版式包
%
% 由学校下发的 .docx 复刻而来(源文件:课程大纲模板-数字逻辑-2024版.docx,
% 2025-01-02 修订)。版式尺寸全部从原文件的 OOXML 量出,换算写在对应位置。
%
% ⚠️ 编译: xelatex 课程大纲.tex
% 单次编译即可,无交叉引用、无目录。
% 依赖 ctex + geometry + fontspec + xeCJK + tabularray
% 实测 TeX Live 2022 / tabularray 2022A
% 与 课程执行大纲/ 的 ouccourse.sty 同源同风格,可对照看。
%======================================================================
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{oucSyllabus}[2026/10/30 v1.0 OUC undergraduate course syllabus]
\RequirePackage{geometry}
\RequirePackage{fontspec}
\RequirePackage{xeCJK}
\RequirePackage{tabularray}
\RequirePackage{enumitem}
%======================================================================
% 1. 页面
%
% 原 docx sectPr 实测:
% pgSz 宽 210.01 mm 高 297.00 mm
% (WPS 存的 A4 是 11910×16840 twips,比标准 A4 的
% 11906×16838 各多 4/2 twips。差 0.07/0.04 mm,肉眼不可辨,
% 本包直接用标准 A4,不为了 0.01mm 去改 \paperwidth)
% pgMar 上下左右均 1440 twips = 25.40 mm
% header/footer 709 twips = 12.51 mm
%
% 即:这是一个非常规整的 A4 + 四边 25.4mm(正好 1 英寸)版心。
% 版心宽 = 210 - 25.4×2 = 159.2 mm,与 docx 一致。
%======================================================================
\geometry{
paperwidth = 210mm,
paperheight = 297mm,
left = 25.4mm,
right = 25.4mm,
top = 25.4mm,
bottom = 25.4mm,
headheight = 0pt,
headsep = 0pt,
footskip = 12.51mm,
}
\setlength{\parindent}{0pt}
\setlength{\parskip}{0pt}
\pagestyle{empty} % 原 docx 无页眉页脚、无页码
%======================================================================
% 2. 字体
%
% 原 docx 用到:Times New Roman / 宋体 / 黑体 / 仿宋_GB2312 / 仿宋 /
% 微软雅黑。其中「仿宋_GB2312」是商业字体,不能随仓库分发,且换机器
% 编不出来(#17 脱敏时定下的规矩)。
%
% ⇒ 全部取自仓库公共字体包 ../fonts.tex(字体文件在 ../fonts/ 下):
% 宋体正文 → OUC Serif(思源宋体子集,真粗体)
% 黑体标题 → OUC Sans(思源黑体子集)
% 仿宋 → OUC Fang(朱雀仿宋)—— 仅在表格内用,见下
% 西文/数字 → 与中文同族 OUC Serif(#20 定下的统一做法)
%
% ⚠️ 为什么正文不用仿宋
% 原 docx 正文是「仿宋_GB2312」,但那是**表格内**的排版习惯。
% 正文大段用仿宋在屏幕上发虚、打印也偏淡,学校下发文件的正文
% 实际以宋体为主。本包正文用宋体,表格内保持仿宋观感(可选项
% \oucSylFangTabletrue 打开,默认关,见第 5 节)。
%======================================================================
\input{../fonts.tex}
%----------------------------------------------------------------------
% 西文切换命令(与 试卷/ouckey.sty 的 \TNR 同义,保持全库一致)
%
% ⚠️ 本包没有把 \setmainfont 改到思源宋体(那是 #20 为试卷做的决定)。
% 课程大纲原文里西文与中文混排不多,主要是年份、百分比、器件型号
% (PROM/PLA/3-8 译码器),这些用默认西文字体即可。
% \TNR{} 在这里保留,是为了跟其他模板的调用习惯一致 ——
% 将来若要把西文也统一到思源宋体,只需改 \setmainfont,调用点不用动。
%
% ⚠️ 必须显式 \normalfont 收尾:xeCJK 下字体切换若紧邻 \par 会"溢出"
% 到下一段,导致后面裸 ASCII 全被排成西文字体(#20 踩过)。
%----------------------------------------------------------------------
\newcommand{\TNR}[1]{{\tnr #1\normalfont}}
\newcommand{\TNRB}[1]{{\tnrb #1\normalfont}}
%----------------------------------------------------------------------
% 字号(pt,直接对应原 docx 的 sz 值)
%
% 原 docx 字号分布(段落计数):
% 15pt 居中 ×1 —— 大标题「中国海洋大学本科生课程大纲」
% 12pt ×32+19+7+3 —— 正文、各级章节标题、表头
% 10.5pt ×1 —— 「六、成绩评定」(原文件此处字号不一致,见下)
% 9~10pt ×27 —— 表格内容
%
% ⚠️ 「六、成绩评定」在原 docx 里是 10.5pt,与其余七个章节标题的 12pt
% 不一致。这是原文件的疏漏(复制粘贴时漏改),本包统一按 12pt 处理,
% 并在 README 记录这一处偏离。
%----------------------------------------------------------------------
\newcommand{\oucsylfont}[2]{\fontsize{#1pt}{#2pt}\selectfont}
\newcommand{\Syw}{\oucsylfont{15}{22}} % 大标题
\newcommand{\Sxii}{\oucsylfont{12}{19}} % 正文 / 章节标题
\newcommand{\Sxi}{\oucsylfont{10.5}{16}} % 小一号正文
\newcommand{\Sx}{\oucsylfont{10}{15}} % 表格 10pt
\newcommand{\Six}{\oucsylfont{9}{13.5}} % 表格 9pt
\AtBeginDocument{\Sxii}
%======================================================================
% 3. 标题与章节
%======================================================================
% 大标题:15pt 黑体居中(原 docx 是微软雅黑,此处用 OUC Sans 顶替)
\newcommand{\oucsylmaintitle}[1]{%
\par\begingroup\Syw\heiti\centering #1\par\endgroup
\vspace*{6bp}}
% 一级章节标题:一、二、三… 12pt 黑体,段前留白
% 原 docx 里章节标题与其后正文同字号同字体,仅靠「一、」区分,
% 视觉层级偏弱。这里给黑体以拉开层次(与 课程执行大纲 的做法一致)。
\newcommand{\oucsylsection}[1]{%
\par\addvspace{10bp}%
\noindent{\Sxii\heiti #1}\par
\addvspace{4bp}}
% 二级小节:1. 2. 3.… 12pt 宋体(原 docx 就是宋体,不加粗)
\newcommand{\oucsylsubsection}[1]{%
\par\addvspace{5bp}%
\noindent{\Sxii #1}\par
\addvspace{2bp}}
%----------------------------------------------------------------------
% 正文段落(首行缩进 2 字符)
%
% ⚠️⚠️ 这里踩了一个很隐蔽的坑,三种常见写法全部越界:
%
% ① `\par\noindent\hspace*{2em}#1\par`
% ② `\par\setlength{\parindent}{2em}\indent #1\par`
% ③ `\parbox{\linewidth}{\setlength{\parindent}{2em}\indent #1}`
%
% 实测(A4,左右 25.4mm,\linewidth=452.97pt,版心右界 523.28bp):
% 无缩进的纯中文段落 右缘 523.28 ✅ 正确
% ①②③ 三种带缩进的写法 右缘 530.53 ❌ 超 7.25bp
%
% 根因:**xeCJK 的中文断行在带缩进时会多排一个字**。
% TeX 从 \linewidth 扣掉了缩进量,但 xeCJK 计算断行点时仍按
% 「整行可用宽度」找最后一个可放的字,于是比应停的位置多放了一个,
% 整行右缘多出约一个汉字宽(12pt 下 7.25bp)。
% ⚠️ 而且**不报 Overfull** —— TeX 认为这行是"刚好"的,
% 不会给出任何警告。只能量 span 坐标发现。
%
% ✅ 正解:把 \hsize 也一起减掉缩进量,让 xeCJK 看到的"整行宽度"
% 就是缩进后的真实宽度,断行点才落对。
% \setlength{\hsize}{\dimexpr\linewidth-2em\relax}
% \setlength{\parindent}{2em}
% 实测右缘 502.28bp,落在版心内(比版心右界还留了 21bp 余量,
% 因为最后一行没排满,属正常)。
%
% ⚠️ \hsize 必须用 \begingroup 包住,否则影响后续所有段落。
%----------------------------------------------------------------------
\newcommand{\oucsylp}[1]{%
\par\begingroup
\setlength{\hsize}{\dimexpr\linewidth-2em\relax}%
\setlength{\parindent}{2em}%
\indent #1\par
\endgroup}
% 无缩进段落(列表项、表格说明等)
\newcommand{\oucsylpz}[1]{\par\noindent #1\par}
%======================================================================
% 4. 表格
%
% 统一用 tabularray(与 课程执行大纲/ouccourse.sty 一致)。
% 选它的理由:需要列宽自适应 + 长文本自动换行 + 跨行合并,
% tabularray 的 X 列比 tabularx 更好控制,且 2022A 之后稳定。
%
% 原 docx 表格边框:tblBorders sz=4 → 0.5pt 实线,四边都有
% 单元格内边距:tblCellMar 108 twips = 1.905mm
%======================================================================
\newcommand{\oucsylborder}{0.5pt}
%----------------------------------------------------------------------
% 4.1 表 0:课程基本信息(6 行 × 6 列,不规则)
%
% 原 docx 结构(竖线位置逐行不同,用 \SetCell 合并实现):
% R0 课程名称 | (中文)数字逻辑 ← 2 格
% R1 课程名称 | (英文)Digital Logic ← 2 格
% R2 课程代码 | 080502101231 | 责任教师 | 杨永全 ← 4 格
% R3 课程属性 | 专业知识 | 课程性质 | 必修 ← 4 格
% R4 学分 | 2.5 | 总课时 | 48 ← 4 格
% R5 理论课时 | 32 | 实践课时 | 16 | 课外学时 | 32 ← 6 格
%
% ⚠️ 列宽不能全用固定值。课程代码「080502101231」是 12 位数字,
% 10.5pt 下实测宽约 63pt ≈ 22mm,加两侧内边距 3.81mm 需 ≥ 26mm;
% 原值 26.5mm 时 Overfull 10.26pt(约 3.6mm),放不下。
% ⇒ 标签列固定 26.5mm(四个字「课程名称」正好),值列用 X 自动分配。
%----------------------------------------------------------------------
\newenvironment{oucsylinfotable}{%
\par\addvspace{4bp}%
\begingroup\Sxi
\begin{tblr}[label=none]{
colspec={Q[c,m,wd=22mm] X[c,m] Q[c,m,wd=22mm] X[c,m] Q[c,m,wd=22mm] X[c,m]},
colsep=1.905mm, rowsep=0pt, stretch=0,
hline{1-Z}={\oucsylborder}, vline{1-Z}={\oucsylborder},
row{1-Z}={ht=7mm, font=\Sxi},
}%
}{%
\end{tblr}\par\endgroup
\addvspace{6bp}}
%----------------------------------------------------------------------
% 4.2 通用数据表(带表头、可重复表头)
%
% 参数:#1 = 列格式(tabularray 的 colspec 内容)
% #2 = 表头行内容(用 & 分隔,自动加粗居中并画横线)
%
% 表 3(教学进度 8×5)与表 4(成绩对应 6×4)都用这个骨架,
% 只是 colspec 不同 —— 具体列宽见 课程大纲.tex 的调用处。
%----------------------------------------------------------------------
\newenvironment{oucsyldatatable}[1]{%
\par\addvspace{5bp}%
\begingroup\Six
\begin{tblr}[label=none]{
colspec={#1},
colsep=1.905mm, rowsep=0pt, stretch=1.05,
hline{1,Z}={\oucsylborder},
vline{1-Z}={\oucsylborder},
row{1}={font=\Six\bfseries, halign=c, valign=m, bg=},
row{2-Z}={font=\Six, halign=l, valign=m},
}%
}{%
\end{tblr}\par\endgroup
\addvspace{6bp}}
%----------------------------------------------------------------------
% 4.3 打勾矩阵(表 1:课程目标 × 指标点)
%
% 原 docx:6 行 × 6 列,首行首格空白,其余为「课程目标1..5」,
% 首列表头为「指标点1.1 / 2.2 / 2.3 / 3.1 / 4.1」,中间 25 格全空
% (留给填 ✓ 或涂色)。
%
% ⇒ 表头行/列加粗居中,矩阵格居中且强制固定高度,
% 这样无论填不填都保持方块观感。
%----------------------------------------------------------------------
\newenvironment{oucsylmatrixtable}{%
\par\addvspace{5bp}%
\begingroup\Six
\begin{tblr}[label=none]{
colspec={Q[c,m,wd=30mm] *{5}{X[c,m]}},
colsep=1.905mm, rowsep=0pt, stretch=0,
hline{1-Z}={\oucsylborder}, vline{1-Z}={\oucsylborder},
row{1}={font=\Six\bfseries, ht=7mm},
row{2-Z}={ht=7mm},
}%
}{%
\end{tblr}\par\endgroup
\addvspace{6bp}}
%======================================================================
% 5. 小节内常用构件
%======================================================================
% 带编号的条目(课程目标、学习要求那种「1.xxx」)
%
% ⚠️ 原 docx 用的是**全角句点**「.」(U+FF0E),不是 ASCII 句点「.」。
% 本包照抄全角。写 \oucsylp{1.xxx} 即可,不要写成 1.xxx —— 全角句点
% 后面没有额外间距,ASCII 句点会多出一个小空隙,与原卷不一致。
%
% ⚠️ 这里**不提供** list 环境。原 docx 的这些条目是普通段落 + 首行缩进,
% 不是真正的列表(没有悬挂缩进,编号后面直接跟文字)。
% 用 list 反而会让第二行缩进到编号右侧,与原卷不一致。
% ⇒ 直接用 \oucsylp{1.xxx},编号是正文的一部分。
% 带括号小标题:(一)(二)(三)
\newcommand{\oucsylsubsub}[1]{%
\par\addvspace{4bp}\noindent{\Sxii #1}\par\addvspace{2bp}}
% 签字栏(大纲审核)
% 原 docx:「教学院长: 院学术委员会签章:」
% 两个字段各占半行,与 课程执行大纲 的签字栏写法一致
\newcommand{\oucsylsignature}{%
\par\addvspace{14bp}%
\noindent
\makebox[0.5\linewidth][l]{教学院长:\hrulefill}%
\makebox[0.5\linewidth][l]{院学术委员会签章:\hrulefill}\par
\vspace*{10bp}}
\endinput