Files
ouc_latex_template/课程大纲/oucSyllabus.sty
T

287 lines
13 KiB
TeX
Raw Normal View History

%======================================================================
% 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