Commit Graph
48 Commits
Author SHA1 Message Date
laoyang 687aa0a5b4 教材:更新 PDF,包含封面图
之前提交源码时用 git checkout 还原了 PDF,导致仓库里的成品
还是无封面图的旧版。本次提交重新编译的版本。
2026-11-01 12:39:07 +08:00
laoyang 203e490197 教材:补上封面图
教材/cover.jpg(1281x1024,229K),教材.tex 启用 \cover{cover.jpg}。
封面图铺满页面上方 210x167.9mm,下方接青绿色带,与成书封面结构一致。

README 文件清单补上 cover.jpg。
2026-11-01 12:03:59 +08:00
laoyang 3906bb49a4 清理代码库中的开发过程内容
- 删除 WORKFLOW.md(开发流程文档,已移入记忆库)
- build.sh 去掉 WSL 相关说明
- 33 个源文件的注释:去掉踩坑记录、实测推导、原文件对比、工单号引用
- 保留技术参数、约束说明、命令含义

净删 399 行。全库 16/16 编译通过。
2026-11-01 09:29:00 +08:00
laoyang f87d763602 重写全部 README,只保留使用说明
17 个 README 统一改成使用说明书,去掉来源、踩坑、需求过程等内容。

只保留:
- 怎么编译、跑几遍
- 文件结构
- 要改哪些参数(逐项列出宏名与含义)
- 用到的命令(表格)
- 版式参数

删除:
- 原文件来源、抽取过程
- 踩坑记录、最小复现、实测数据
- 用户需求、工单号、历史沿革
- 改造前后对比

行数 4185 → 2261。

全库 16/16 编译通过。
2026-11-01 08:52:54 +08:00
laoyang a4bfcac82a 新增《教材》LaTeX 模板,从 sre 教材抽取版式骨架 #25
源:D:\Yongquan\code\sre =《软件需求工程导论》完整教材
(13 章 + 5 附录,78 万字节,265 页 PDF,elegantbook 文档类)

## 新增文件

   教材/ouctextbook.sty    版式配置
   教材/elegantbook.cls    本地化过的文档类(改过字体)
   教材/教材.tex           示例正文(1 章 + 附录 + 参考文献)
   教材/reference.bib      参考文献库(虚构条目)
   教材/README.md          用法 + 踩坑记录

## 核心约束:字体的共用性

用户明确要求「注意字体的共用性」。原教材用 elegantbook 的
chinesefont=founder 档,加载方正四大字体:

   FZShuSong-Z01 / FZHei-B01 / FZKai-Z03 / FZFangSong-Z02

这些是**商业字体,不能随仓库分发**(#17 定下的规矩)。

### elegantbook 三档字体全都不通用

| 选项 | 实际字体 | 问题 |
|---|---|---|
| founder(默认) | 方正四大字体 | 商业字体,换机器就废 |
| ctexfont | 系统字体(Win=SimSun,macOS=PingFang) | 三平台三种样子 |
| nofont | 不设 | 不配置就报错 |

### 只写 nofont 还不够 —— cls 自身还硬编码字体

elegantbook.cls 第 176/184 行:

   \setmainfont{TeXGyreTermesX}[...]
   \setsansfont{texgyreheros}[...]

这两款在精简 TeX Live 上都没有,报 9 个错误连发:

   ! Package fontspec Error: The font "texgyreheros-regular" cannot be found

**实测:在 \documentclass 之后用 \setsansfont 覆盖无效** ——
类加载时字体族已注册失败,后面重新指定救不回来。

⇒ 所以本模板必须带一份**本地化的 cls**,改三处(都留了"本地化"注释):

| 位置 | 改动 |
|---|---|
| ~176 行 | TeXGyreTermesX → texgyretermes + Path=../fonts/tex-gyre-termes/ |
| ~184 行 | texgyreheros → OUCSans + Path=../fonts/ouc-sans/ |
| \maketitle | example-image → \ouc@coverblank |

这是本模板与仓库其他模板的**唯一结构性差异**:别的模板只要
\input{../fonts.tex},本模板还要那份改过字体的 cls。

## 踩到的三个坑

### 1. 封面不写 \cover{} 会插一张 "Image" 占位图

cls 第 1288~1300 行:
   \ifcsname @cover\endcsname ... \else
     \includegraphics[width=\linewidth]{example-image}   ← mwe 的灰底占位图

首页顶着 "Image" 两个大字。已把 else 分支换成空盒子。

### 2. 占位盒宽度不能是 0(这个坑耗了最久)

第一版 \rule{0pt}{0pt}(0 宽),立刻冒出:

   Overfull \hbox (5.00002pt too wide) in paragraph at lines 44--44

试过全部无效,溢出量死钉在 5.00002pt 不动:
  改 \hspace{2em} / \hspace{2.5em}     无效
  改 minipage 的 0.67/0.27\linewidth   无效
  改 tabular 列间距 @{}l@{}            无效
  改 \colorbox 的 \makebox[\hsize]     无效

根因:0 宽空盒让 \linewidth 在 titlepage 里与 \textwidth 差 5pt,
后续并排的 \parbox{0.8\textwidth} + 两个 minipage 整体超宽。

✅ 正解:给占位盒满宽
   \newcommand{\ouc@coverblank}{%
     \rule{0pt}{0pt}\hspace{\linewidth}\rule{0pt}{0pt}}
实测 0 Overfull。

### 3. 封面色带改不动(一行 \colorlet 的位置问题)

cls 第 345 行 `\colorlet{coverlinecolor}{second}` 在**类加载末尾**执行,
把 coverlinecolor 绑到 second 色(black 模式下就是黑)。

⇒ 导言区写 \colorlet 会被覆盖,实测色带仍是纯黑。
必须用 \AtBeginDocument 排到它后面。

## build.sh 补了 bibtex 支持

原来只跑两遍 xelatex,教材的参考文献出不来。
新增:目录下有 .bib(排除 *-blx.bib 这种中间产物)就插一次 bibtex,
再补一遍 xelatex,最后跑统计那一遍。

## 验证

   8 页  error 0  Overfull 0  Underfull 0
   封面色带 RGB(32,178,170) 青绿,实测 fill=(0.125,0.698,0.667)
   封面无 example-image 占位

字体(PDF 内嵌实测,全部来自仓库):
   OUCSerif-Regular / -Bold        中文正文
   OUCKai-Regular                  中文斜体(楷体代)
   TeXGyreTermes-Regular/-Bold/-Italic   西文
   LMMono10-Regular                \texttt 等宽(TeX Live 自带)

→ **无方正、无 SimSun/SimHei、无 Times New Roman**

全库 16/16 通过(新增第 16 项,已加入 verify_all.sh)。

⚠️ Windows 端本机未能编译:TeX Live 写字体缓存
(C:\texlive\2022\texmf-var)被安全策略拦截,属环境限制非模板问题。
模板只依赖 TeX Live 标准宏包与发行版自带字体;原教材本身就是在
Windows + TeX Live 2022 上编出来的。

## .gitignore 补充

新增 *-blx.bib、*.run.xml(biblatex 中间产物)、*/.preview/(预览图)。

## 与原教材的差异

| 项 | 原教材 | 本模板 | 原因 |
|---|---|---|---|
| 封面图 | cover.jpg | 无(纯色带) | 模板不附图片 |
| 字体 | 方正四大字体 | 仓库开源字体 | 商业字体不能分发 |
| 西文无衬线 | texgyreheros | OUC Sans | 仓库没有 Hero |
| 正文 | 13 章 265 页 | 1 章示例 | 只抽骨架 |
2026-11-01 08:06:22 +08:00
laoyang c4e686de11 清理:不提交预览图 #24 2026-10-30 23:37:16 +08:00
laoyang 333e2a7789 会议预算表:修掉多出的一列,签字盖章间距拉开 #24
用户反馈两点:
  ① 所在单位负责人意见下面,签字和盖章距离太近
  ② 表格右侧整体多出一列

## ② 多出一列的根因

实测竖线 **9 条 = 8 列**,而 colspec 只定义了 7 列。
多出来那列宽 2.18mm,横贯全部 28 行。

定位过程:
  删掉 R27/R28(意见+签字两行)→ 变 8 条竖线(7 列,正确)
  加回去 → 又变 9 条
  ⇒ 问题就在这两行。

四种组合全试过,全部失败:

| 内容段数 | cell 声明 | 结果 |
|---|---|---|
| 8 段(7 个 &) | cell{27}{4}={c=4} | 9 条竖线,多一列 ❌ |
| 7 段(6 个 &) | cell{27}{4}={c=4} | 9 条竖线,多一列 ❌ |
| 2 段(1 个 &) | cell{27}{4}={c=4} | 列数对,但第 2 段被合并盖住,内容消失 ❌ |
| 2 段 | cell{27}{2}={c=6} | 网格散架(3 页、横线全无)❌ |
| 7 段 | 无 cell 声明 | 同样散架 ❌ |

根因:tabularray 2022A 对「跨整行的大合并」处理不稳定,要求
「内容段数 / cell 起始列 / 跨度」三者严格自洽;在固定列宽 + colsep
1.0mm 的组合下,这三者无法同时满足。

### 解法:物理隔离

主表只到 R26「合计」(26 行),R27/R28 用独立的 oucmeetsign 环境
紧贴在下方。视觉上是同一张表,排版上互不干扰。

签字表列宽**不能自己估**,必须按主表实际竖线位置反推:
   主表竖线 79.65~514.31 = 153.34mm
   3:4 分界 231.89 -> 距左 53.71mm
   第1列 wd = 53.71 - 2 = 51.71mm
   第2列 wd = 153.34 - 53.71 - 2 = 97.63mm
(减 2 = 两侧 colsep 各 1mm)

⚠️ 第一版估的 47.18/93.80 总宽只有 144.98mm,比主表窄 10.5mm,
边框对不上,两格在 pymupdf 里连成一串,看着像只有一格。

## ① 签字盖章间距

3em(27bp=9.5mm) → 5em(45bp=15.8mm)。
实测「(签字)」右端 274.2,「(盖章)」左端 319.0,间距 44.8bp = 15.8mm。

⚠️ 第 1 格的「(签字)」不能用 \hfill 推到右边:第 1 格宽 51.71mm=146bp,
「(签字)」36bp,\hfill 推到格尾后文字**溢出单元格右边界**
(tabularray 不裁剪格内容),实测跑到 199~265 跨过分界线 232,
和第二个「(签字)」连成一串。
⇒ 直接顶格左排,前面补 1mm 抵消全角括号的字形左空白
(「(」的 ink 起点比盒起点靠左 2.5bp,不加会超出左界 79.40)。

## 验证

   主表竖线 8 条 -> **7 列**(多出的列已消除)
   内容核查 49 项,**缺失 0**
   校级领导意见 0 次
   其他费用竖排 y 531.3~586.4,上下留白各 13.4bp
   1 页  err 0  Overfull 0  Underfull 0
   最左 79.40(界79.40)  最右 521.58(界521.57)  最下 711.80(界742.65)

全库 15/15 通过。双端一致:
   WSL TeX Live 2025      1 页 err=0 over=0 under=0
   Windows TeX Live 2022  1 页 err=0 over=0 under=0
2026-10-30 23:37:12 +08:00
laoyang 2e79b00d50 会议预算表:其他费用字距收回,不再贴格线 #24
用户指出:「其他费用,五个字,不能跟那个格子一样高啊,这样字和表格的
线都连在一起了。」

## 问题

上一版为了让四字"填满 5 行",把 \\ 的行距拉到 \\[17bp],
结果文字块高 94bp,而合并格只有 81.9bp —— **文字块比格还高**,
头尾字距格线只剩 2.5bp,视觉上字和表格横线糊成一片。

## 修正

字距改 \\[4bp]。实测对比(9pt 字,合并格高 81.9bp):

   \\[17bp]  文字块 94bp   上下留白 2.5bp    ❌ 贴线
   \\[8bp]   文字块 67bp   上下留白 7.4bp    ⚠️ 偏挤
   \\[4bp]   文字块 56bp   上下留白 13.4bp   ✅ 采用
   不加参数  文字块 43bp   上下留白 19bp     ⚠️ 挤成一团,看不出竖排

## 验证(坐标实测)

   四字 y: 531.3~540.2 / 546.9~555.8 / 562.1~571.0 / 577.4~586.4
   合并格 y: 517.9 ~ 599.8   高 81.9 bp
   距上格线 13.4 bp   距下格线 13.4 bp   ← 完全对称居中

   1 页  error 0  Overfull 0  Underfull 0
   最右 521.58(版心限 521.57)  最下 710.30(版心底 742.65)
   表格宽 155.52 mm(版心 155.99 mm)

全库 15/15 通过。双端一致:
   WSL TeX Live 2025      1 页 err=0 over=0 under=0
   Windows TeX Live 2022  1 页 err=0 over=0 under=0

## 顺便记录

README 里加了字距对照表,说明为什么必须卡在 4bp,避免以后又调回大值。
2026-10-30 20:17:03 +08:00
laoyang f42e6e398a 会议预算表:修正四处排版问题 #24
用户反馈四点,逐条修。

## ① 会议时间与会议地点位置错乱

**现象**:两个字挤在一起,中间没有留填写区。

**根因**:tabularray 的 cell{} 合并位置决定标签落在哪一格,
不是"第几个字"。R2 的合并是 2+2+2+1,即
   格1(列1-2)=会议时间   格3(列3-4)=空值
   格5(列5-6)=会议地点   格7(列7)=空值
「会议地点」必须写在第 5 段,我原先写在第 3 段。

**顺带查清 tabularray 的一个静默失败**(最小复现):
写 7 段 `甲 & & 乙 & & 丙 & & 丁` → 四个字全对
写 4 段 `甲 & 乙 & 丙 & 丁`         → **乙、丁 被吞掉,不报错**
⇒ 段数必须等于列数,被合并的格留空。

**修正**:`会议时间 & & & & 会议地点 & & \\`
实测:会议时间 x=118.6(列1-2),会议地点 x=324.1(列5-6),
中间 193~289 是填写区。

## ② 其他费用应为竖排,不是旋转 90°

**根因**:`\rotatebox{90}` 只是把横排整句转个角度,
不是"上下排列"。用户要的是逐字竖着叠。

**修正**:改 `\shortstack{其\\[17bp]他\\[17bp]费\\[17bp]用}`,
并用 `cell{21}{1}={r=5}{c}` 做纵向合并 5 行。

实测:格高 82bp(y 517.9~611.7),四字 y=517.7/546.4/574.6/602.9,
字距 28.7bp,基本填满。

⚠️ 拉字距**不能**用局部 `\baselineskip` —— `\shortstack` 内部会重置它,
实测设 19bp 完全无效(字距仍是 11.6bp)。必须在 `\\` 上给可选参数。
⚠️ 也**不能**用 `\parbox{}{其\\他\\费\\用}` —— 会变成 4 个独立行盒子,
tabularray 排版错乱,四个字跑到不同段落(实测)。

⚠️ 之前认为「纵向合并和横向合并不能共存」,那是因为写在内容里用
`\SetCell[r=n]`;改用 cell{} 矩阵语法后**可以共存**,本条即证据。
第 2 节的说法已相应更正。

## ③ 校级领导意见是多余的

**先核实**:源 .doc 的 R26 第二格里**确实有两个段落**——
「所在单位负责人意见:」和「校级领导意见:」。
用 LibreOffice 直接转 txt 核过,原文件就有,不是转换时多出来的。

**但用户确认这份表不需要校级领导,故删除。**

代码里注明了原文件有两个段落,要恢复时加回来且必须单独一行。

## 顺带

去掉 `\RequirePackage{graphicx}` —— 不再用 \rotatebox,减少一个依赖。

## 验证

   1 页   error 0   Overfull 0   Underfull 0
   表格 155.52mm / 版心 155.99mm  界内
   最右 521.58(版心止 521.57)  最下 722.27(版心底 742.65)
   校级领导意见 出现 0 次
   会议时间/会议地点 相距 205bp 中间留空

全库 15/15 通过。双端一致:
   WSL TeX Live 2025     1 页 err=0 over=0 under=0
   Windows TeX Live 2022  1 页 err=0 over=0 under=0
2026-10-30 20:11:50 +08:00
laoyang 1c67b7ded1 新增《会议预算表》LaTeX 模板 #24
源文件:微信收到的 会议预算表.doc(51712 字节,**OLE2 老式 .doc**,
D0CF11E0 签名)。python-docx 读不了,处理链路:
.doc --(LibreOffice headless)--> .docx --(python-docx)--> 结构

## 新增文件

   会议预算表/oucmeeting.sty   版式包(含全部 28 行合并规则)
   会议预算表/会议预算表.tex   空表正文(只有内容,无 \SetCell)
   会议预算表/README.md        用法 + 踩坑记录

## 版式(实测)

   页面    A4 210×297mm
   边距    top 38.01 / bottom 35.01 / left 28.01 / right 26.00 mm
   版心    155.99 × 223.98 mm
   字号    标题 22pt,表格与说明 9pt
   表格    28 行 × 7 列,边框 0.5pt,行高 5.6mm

四个边距都不常见,是原表为把 28 行塞进一页压出来的。照抄不"优化"。

⚠️ 原表宽 169.12mm(tblGrid 9588 twips),**比分宽出版心 13.12mm**,
原 docx 靠 fixed 布局硬撑、实际压进页边距。本模板等比缩到版心内。

## 三个踩了很久的坑(全部写进代码注释 + README)

### 1. 合并必须用矩阵式语法,不能写 \SetCell

在这套 7 列 Q[c,m,wd=…] + colsep=1.0mm 配置下,内容里一写
\SetCell[c=n] 就报:

   ! Missing number, treated as zero.
   ! Illegal unit of measure (pt inserted.)
   \__dim_eval_end:

**所有错误都定位到 \end{tblr}**,完全看不出是哪个格。
最小复现(已验证):
   \begin{tblr}{colspec={Q[c,m,wd=21mm]...7列..., colsep=0.8mm}}
     \SetCell[c=2]{c} A & \SetCell[c=5]{l} B \\
   \end{tblr}   % 必崩

✅ 正解:在 tblr 选项里用 cell{行}{列}={c=n}{对齐},被合并格留空。

这个坑吃掉最多时间 —— 因为报错行号指向 \end{tblr},
试过 \shortstack、\rotatebox、\newline 各种改,全都不对,
最后靠「同一合并规则换成 cell{} 语法就 0 错」的最小复现才定位到。

### 2. \SetCell[r=n] 与 \SetCell[c=m] 不能同现

纵向合并和横向合并放同一行,报同样那串错。
本表完全不用纵向合并 —— 「其他费用」改成 \rotatebox{90} 竖排,
第 1 列下面 4 行留空,视觉等价。

### 3. colspec / hline / vline / ht 参数不能用宏

tabularray 用自带展开器解析这些选项,遇到用户宏直接
`! Undefined control sequence.`。全部写字面值。

## 页高预算(关键,别乱改行高)

   28 × 5.6mm = 156.8mm
   标题区(附件1 + 22pt 标题 + 日期行)≈ 30mm
   说明 3 条(第 2 条占两行)≈ 35mm
   合计 ≈ 222mm  ≤ 223.98mm  ✅ 刚好一页

⚠️ 行高 5.6mm 已在下限附近。改回 6.0mm 会让 28 行多出 11.2mm,
第 3 条说明立刻被挤到第 2 页(实测过)。

## 验证

   1 页   error 0   Overfull 0   Underfull 0
   表格 155.52mm / 版心 155.99mm  → 界内
   内容 50 项逐项核对,全部存在
   (唯一"缺失"项是「不得坐支现金」因跨行被 \n 断开,
     去空白后匹配通过 —— 不是真缺失)

全库 bash build.sh all → **15/15 通过**(新增第 15 项,已加入 verify_all.sh)

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

## 说明

空表,金额/卡号/日期/人名一律留空。不含任何真实数据。
2026-10-30 16:50:32 +08:00
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
laoyang 42c1394aec 答案卷抬头改为一行一项,修复长学院名重叠 #22
## 用户诉求

「评分标准最开始不是有个表格吗,里面有开课学院什么的,如果学院名字太长,
就和后面课程名称重合在一起了。看看怎么解决。我建议一行一个信息,
因为这个又不怕长,如果太长,一行都放不下,就直接换行。」

## 现象(已复现并量化)

`dept` 填超长值后,pymupdf 读出:

    开课学院:(70.87~123.37)  值:(123.37~406.87)

而第二格「课程名称」本该从 216.0 开始 ⇒ **重叠 190.87bp**,
把「课程名称 / 试卷类型」整个压住。

⚠️ **编译完全不报错,也没有 Overfull**(rc=0 over=0)。
`\makebox` 内容溢出盒外时 TeX 不认为是坏行。这类 bug 只能靠
量 span 坐标发现,看日志发现不了。

## 根因

`\ouckey@inforow` 用三个 `\makebox[0.3333\linewidth][l]` 并排。
`\makebox` 是**不可断盒子**:
- 内容比盒宽短 → 左对齐(正常)
- 内容比盒宽长 → **直接溢出盒外,压到右边一格**(就是 bug)
- 盒内中文**不能换行**(LR 模式,不做段落断行)

⇒ 三格布局对短字段友好,对长字段必然重叠。

## 改动一:一行一项

    \newcommand{\ouckey@inforow}[2]{%
      \ouckey@ifempty{#2}{}{%
        {\fontsize{10.5bp}{15bp}\selectfont
         \par\noindent\textbf{#1:}#2\par}}}

调用点从「三参数一组」改成「两参数一行」,共 9 项:
课程名称 / 开课学院 / 学生学院 / 年级专业 / 试卷类型 / 考试方式 /
任课教师 / 命题人 / 满分。顺序按"读者关心程度"排。

行距收紧到 15bp(`\Fivhao` 基线距是 16bp)—— 抬头是查阅信息,
不需要正文行距;9 行省约 52bp,将近 3 行正文。

## 改动二:附带修掉一个旧版就有的判空 bug

**旧实现**:
    \newcommand{\ouckey@ifempty}[1]{%
      \if\relax\detokenize{#1}\relax ... }
调用 `\ouckey@ifempty{\ouckey@dept}{空}{非空}`。
`\detokenize` **不展开参数**,看到的是字符串 `\ouckey@dept`(宏名),
永远非空 ⇒ 判空永远失败。

后果:`dept = {}` 时抬头印出孤立的「开课学院:」,后面没有值。
这是旧版就有的 bug(三格布局下不明显),改成一行一项后暴露。

**修法**:在 `\define@key` 里就规范化空值,新增
    \newcommand{\ouckey@setkey}[2]{%
      \if\relax\detokenize{#2}\relax \def#1{}\else \def#1{#2}\fi}
13 个 key 全改走它。

⚠️ 试过「先 `\edef` 展开再 `\detokenize`」的写法,报
   `! Incomplete \iffalse` —— `\if...\else...\fi` 被 `\expandafter`
   链打散,TeX 匹配 `\fi` 时错位。这类宏层展开的修补太脆,放弃。
⚠️ `\ouckey@setkey` 必须定义在 `\define@key` **之前**,否则 undefined。

## 验证

### 三个场景

| 场景 | 结果 |
|---|---|
| 正常(学院名 12 字) | 9 项齐全,无重叠,无越界 |
| 长(含括号说明,约 40 字) | 单行排到 x=406.90,无重叠(下面没有格子可压) |
| 极长(约 70 字) | **自动换行成两行**,第二行缩进对齐,右缘正好 524.40 |
| 留空(dept/college/major 全空) | 三项**整项不印**,不留空行 |

### 编译

    试卷题型示例        6 页  err=0 over=0
    参考答案与评分标准  4 页  err=0 over=0

全库 `bash build.sh all` → **13/13 通过,0 失败**。

### 页数变化

答案卷 3 页 → 4 页。抬头从 3 行变 9 行,是「一行一项」的必然代价。
**已向用户确认,接受 4 页**(第 4 页只有说明文字末尾 2 行 + 签字行)。

## 示例文件未改

`参考答案与评分标准示例.tex` 测试后已还原,`git diff` 为空。
只改 `ouckey.sty` 一个文件。
2026-10-29 22:58:34 +08:00
laoyang 6819d78f29 工作流全部迁到 WSL:新增 WORKFLOW.md,build.sh 改为 WSL 原生 #21
用户要求「全部在 wsl 完成」,原因是 Windows 上工作太多太乱,
WSL 像虚拟环境、坏了能重置、不影响系统。

## 之前为什么乱

分工是「Windows 改代码 + 两端都编」:Windows 侧一份仓库副本装满了
.aux/.log/.toc/.pdf,WSL 侧另一份,靠 scp/git pull 同步维持。
同一项目两份工作副本,漏同步就分叉。

## 实测确认的技术前提

1. **UNC 路径双向读写** —— `\\wsl$\Ubuntu-26.04\home\yongquan\...`
   Read/Write/Edit 三个工具都能直接作用于该路径,读写均落到 WSL 磁盘。
   延迟 6~63ms。⇒ 不需要「本地编辑 → scp」这套中间环节。
   ⚠️ 发行版名是 Ubuntu-26.04,不是常见的 Ubuntu 或 Ubuntu-22.04。

2. **WSL 内 TeX 可完整编译全库** —— `bash build.sh all` 13/13 通过。

3. **WSL 内 git 可推送** —— credential.helper=store 已指向含 token 的
   ~/.git-credentials,fetch 实测通过。

4. **gi.py 可迁** —— 纯标准库,无第三方依赖,复制即用。

5. **Python 依赖** —— 建 ~/.venv-latex,装 pymupdf 2.0 + fonttools 4.68.0,
   不污染系统 Python。

## 本 commit 的改动

### 新增 WORKFLOW.md
写清:为什么在 WSL、目录位置(含 UNC 路径)、日常命令、编辑方式、
PDF 不进版本库的原因、已知排版告警清单、环境重建步骤。

### build.sh 重写为 WSL 原生
原版是「Windows 通过 ssh 远程调 WSL 编译再 scp 取回」,在 WSL 内跑没意义。

新版改动:
- 去掉全部 ssh/scp,直接本地编译
- 两遍编译(目录/页码/LastPage 跨引用第二遍才稳定)
- 自动 cd 到模板目录(.sty 的 ../fonts/ 相对编译目录解析)
- 目录→主文件映射保留:幻灯片/slides、科技报告/report、
  试卷有两个主文件必须显式指定、简历不能拿 ls 第一个 .tex
- `all` 转给 verify_all.sh(那边有完整 TARGETS 清单)
- 新增 SILENT=1 输出紧凑表格,便于脚本消费
- 单目录模式找不到时列出可选目录/主文件,不用去翻源码

### WSL 侧环境(不入库,属个人配置)
- ~/.config/ouc-latex/env.sh 固定 OUC_PY / GI / WB_GITEA_CONFIG / OUC_REPO,
  提供 gi / ouccd / texbuild 别名
- ~/.bashrc 末尾 source
- ~/.local/bin/gi.py + ~/.config/ouc-latex/gitea.json(chmod 600)

## 验证

WSL 内全库编译:

    总数 13 | 通过 13 | 失败 0

逐项:劳务发放说明表 1 / 年度考核登记表 2 / 幻灯片 30(UF1) /
成绩构成说明 1 / 特殊事项说明表 1 / 科技报告 10(UF4) / 简历 3 /
试卷题型示例 6 / 参考答案 3 / 试卷归档封面 1 / 试卷归档目录 1 /
课程执行大纲 5(OF1) / 课程教学日历 2

页数与 Windows 侧历史记录逐个一致。3 处告警均为既有问题,非回归。

WSL 内工单工具:`gi whoami` → token 有效、仓库识别为 ouc_latex_template。
本工单 #21 即由 WSL 内的 gi 创建,工具链已实证可用。

## Windows 侧

备份 D:\Yongquan\backup\ouc_latex_template-win-backup-20261029.tar.gz
(49MB / 244 项 / 不含 .git)。删除前确认两端 HEAD 同为 fb7c76b、
无未推送提交、无 stash。备份保留,不删。

涉及文件:WORKFLOW.md(新增)、build.sh(重写)
2026-10-29 21:50:34 +08:00
laoyang fb7c76b944 装订线虚线方向修正:横杠改回竖杠 #20
用户反馈:「这个装订线不行,得改,需要跟之前的模板保持一致。」

## 问题:整条装订线成了「梯子」

#20 把连字符虚线改成几何线画时,方向画反了。逐像素对比基线与修改后:

  基线(18bp 连字符 rotate 90°):x 51.10~52.10(宽 1.10)、y 跨 4.30
  改后(我画的水平线)    :x 49.40~53.70(宽 4.30)、y 跨 1.00

即基线的每一笔是**竖着的短杠**,我画成了**横着的短杠**。一排横杠叠在
竖线位置上,视觉上就是一把梯子,与原卷完全不同。

## 根因:量数据时没分辨长宽各自对应哪个轴

上一轮 720dpi 扫描得到「长 4.40bp、粗 1.10bp、x 中心 51.60bp」,
三个数都对,但**装配时把「长」放到了 x 轴、「粗」放到了线宽**。
连字符经 rotate=90 后,字面长度落到**纵轴**、线粗落到**横轴**:

  竖:y 跨 4.30bp(连字符的字面长度)
  横:x 跨 1.10bp(连字符的笔画粗细)
  中心 x = 51.60bp

## 修法

  - \draw[line width=1.10bp] (49.40, -y) -- (53.70, -y);     ← 水平线(错)
  + \draw[line width=1.10bp] (51.60, -y) -- (51.60, -y-4.30); ← 竖直线(对)

x 恒定在 51.60,y 跨 4.30bp。单笔画长度用 4.30(720dpi 实测的墨迹边界),
不是之前写的 4.40(那是含抗锯齿溢出的粗估值)。

## 验证:与基线逐像素同值

装订线区域(x 48~56, y 55~690)在 300dpi 下的墨迹像素数:

  基线  7553 像素(8.40%)
  新版  7553 像素(8.40%)  ← 完全相同

逐段比对(720dpi 逐行扫描,过滤掉「装订线」三个汉字的干扰):

  段  笔数   顶端 y    末笔底 y   单笔长   笔距
   1   24    62.20     204.90     4.30    6.00
   2   24   216.50     358.60     4.30    6.00
   3    3   364.80     379.50     4.30    6.00
   4   13   393.40     469.60     4.30    6.00
   5   16   475.80     568.30     4.30    6.00
   6   16   582.10     676.30     4.30    6.00

新版逐段同值,单笔长 4.20 vs 4.30 的 0.1bp 差异是抗锯齿边缘取整。
x 位置 51.00~52.00 vs 51.10~52.10 同样差 0.1bp(亚像素取整),肉眼不可见。

## 编译验证

  Windows / TeX Live 2022   试卷 rc=0 err=0 over=0 6页
                            答案卷 rc=0 err=0 over=0 3页
  WSL / TeX Live 2025       试卷 rc=0 err=0 over=0 6页
                            答案卷 rc=0 err=0 over=0 3页

答案卷不走装订线(\oucexam 的 shipout 钩子只属于试卷),未受影响。

涉及文件:试卷/oucexam.sty(仅 \ouc@dashseg 一个宏 + 注释)
2026-10-29 21:35:57 +08:00
laoyang 93b03c8a78 试卷字体统一为思源宋体 #20
用户要求:「试卷的字体,需要改一下,全部都用思源宋体就可以了。」

pymupdf 提取两份成品 PDF 定位到四类需要统一的字体:

  试卷题型示例(6 页)            参考答案与评分标准示例(3 页)
  OUCSerif-Regular 203 中文        OUCSerif-Regular 333 中文
  TeXGyreTermes-Regular 133 西文   TeXGyreTermes-Regular 197 西文
  TeXGyreTermes-Bold 85 题号分值   OUCSans-Regular 37 黑体小标题
  OUCSerif-Bold 81 中文加粗         CMR10/CMMI10/CMSY10 49 数学公式
  OUCKai-Regular 25 卷头与成绩表    TeXGyreTermes-Bold 21 数字

一、西文与数字:Termes → 思源宋体(oucexam.sty / ouckey.sty)

先在包里用 \newfontfamily 登记 \OUCLatinSerif / \OUCLatinSerifBold
(四个档位全给,斜体指回 Regular —— 思源宋体没有真斜体),再把
\tnr / \tnrb / \sunfont 都 \let 过去。

⚠️ 只做这一步**不够**,这点踩了一轮:模板里大量文字根本没走 \tnr,
而是走 \setmainfont(默认西文族)——\textbf{learning outcome} 的裸西文、
页脚的页码与总页数、任何 \selectfont 之后的裸 ASCII。
第一轮只 \let 时,PDF 里仍残留 22 个 TeXGyreTermes span:
页脚 6 个页码 + 6 个总页数 + 第 4 页的 A./B./C./D. 与 learning outcome 等。
⇒ 必须连 \setmainfont / \setsansfont 一起指到 OUCSerif。

二、卷头与成绩表题号:霞鹜文楷 → 思源宋体(oucexam.sty)

\kh 与 \scoretable 用 \kaiti。包里 \let\kaiti\songti 一次性收口,
不动 ../fonts.tex 的 \def\kaiti —— 别的模板还要用楷体。

三、答案卷黑体小标题:思源黑体 → 思源宋体(ouckey.sty)

\heiti 共 37 处(卷头大标题与各节小标题)。同样 \let\heiti\songti。

四、数学公式:保持不动

$x$ / $\dfrac{1}{45}\sum f_i x_i$ 等 49 处仍走 Computer Modern。
思源宋体没有 MATH 表(实测只有 GSUB/GPOS),不能作数学字体;
强行塞进正文字体会破坏斜体变量、正体数字、运算符间距。用户已确认。

五、装订线虚线:连字符排字 → 用线画(oucexam.sty)

原卷那 6 段竖虚线是 18bp Times 连字符排出来的。换成思源宋体后连字符
每个宽 0.346 em(Termes 0.333),每串会长 4~7bp,破坏"复刻原卷长度"。
⇒ 改为几何画的短横线段,长度锁死。实测原卷(720dpi 逐笔画测量):
  单个连字符笔画 长 4.40bp、粗 1.10bp、x 中心 51.60bp
  相邻笔画步距 6.00bp
新增 \ouc@dashseg{起点y}{笔画数},六段坐标与笔画数逐段照抄原卷
(含原卷被白底遮断成 13+3 两截的那一段)。
⚠️ \newcommand 必须定义在 \ouc@dobindstrip 外面,否则每次 shipout
重新定义,第二页起报 already defined。
⚠️ y 坐标不能写 \dimexpr#1bp+\i*6bp —— TikZ 坐标解析器不认小数 +
\dimexpr 组合,报 Illegal unit of measure。要先 \pgfmathsetmacro。

六、直引号归入 CJK(ouckey.sty)

答案卷正文用 ASCII 直引号 "" 表示中文引号(32 处)。U+0022 在
Basic Latin,xeCJK 判为西文 ⇒ 引号走 \setmainfont,与两侧汉字不同字体,
并挤压出 Overfull(第 88 行 +8.07pt)。
\xeCJKDeclareCharClass{CJK}{"0022} 归位后解决。
⚠️ 不在 fonts.tex 里改:那里全库共用,会让正文真正的英文引号(代码
   片段 "hello world")也变全角。

七、Overfull 的修法:改源码断行,不调参数(ouckey.sty 留有完整记录)

换字体后 \keyitem{3}{4} 那段 Overfull 2.61pt,实际压出版心
(最右 527.01bp,版心止于 524.41)。试过并确认**全部无效**的五种:
  · \emergencystretch 1.5em —— 本行没有弹性胶可拉,无从施展
  · \tolerance 3000 —— 不是不满意断点,是没有更早的合法断点
  · PunctStyle=kaiming —— 能消 Overfull,但标点悬挂探出版心 6.5bp
  · PunctStyle=quanjiao —— 同样探出 8bp
    (xeCJK 这几个 PunctStyle 做的是"标点悬挂"不是"标点压缩",
      指望它消 Overfull 必翻车)
  · \rightskip 0pt plus 6bp(含 \AtBeginDocument 版)—— 6bp 远小于
    需要的 150bp,TeX 仍选"撑破"这个解
正解:第 124 行句号「。」后加 \\。分项给分的答案本来就该一句一行,
读者靠句号扫分点 —— 既解决排版,又让内容结构更清楚。

验证(两套环境各跑,逐项同数)

  WSL / TeX Live 2025    试卷 rc=0 err=0 over=0 6页
                         答案卷 rc=0 err=0 over=0 3页
  Windows / TeX Live 2022 试卷 rc=0 err=0 over=0 6页
                         答案卷 rc=0 err=0 over=0 3页

pymupdf 提取字体分布:

  试卷题型示例      OUCSerif-Regular 291 + OUCSerif-Bold 70
                    → 非宋体文字字体:无
  参考答案示例      OUCSerif-Regular 235 + OUCSerif-Bold 53
                    + CMR10/CMMI10/CMSY10/CMMI7/CMEX10(数学,保留)
                    → 非宋体文字字体:无

几何核对(逐 span 比对,均与基线一致或更优):
  · 成绩表 17 栏逐字符坐标与基线**完全相同**(硬编码坐标,不受字体影响)
  · 装订线 96 笔全部绘出:x 49.40~53.60(宽 4.40bp)、步距 6.00bp,
    六段位置与原卷实测一致
  · 三页最右墨迹均为 524.41bp,与版心严丝合缝,无越界
  · 试卷 6 页最右最大 523.33bp(第 4 页 \mtpair 的 44% 栏宽设计,
    基线同位置同样数值,非本次引入)

涉及文件:
  试卷/oucexam.sty                 默认族、西文字族、\kaiti、装订线虚线
  试卷/ouckey.sty                  默认族、西文字族、\heiti、直引号、踩坑记录
  试卷/参考答案与评分标准示例.tex  第 124 行句号后加断行
2026-10-29 21:29:15 +08:00
laoyang 5d59aa1853 科技报告字体调整:西文改 Cochineal、标题统一鸿蒙、代码换等宽 #19
用户反馈「标题一会儿黑体一会儿什么体的」。pymupdf 提取旧 PDF 定位到
三处字体分裂,逐条修掉。

一、西文从鸿蒙换成 Cochineal(cls/font.cls)

旧版 \setmainfont / \setsansfont / \setmonofont 三处全是鸿蒙。中文换成
思源宋体之后,正文就成了「中文衬线 + 西文无衬线」:同一行里英文数字比
汉字细、像陷进去,读起来割裂。

Cochineal 是 Minion 风格的衬线体(OFL 1.1,fonts/cochineal/ 已在库内),
与思源宋体灰度接近;度量与 Termes 只差 1.9%,不推着断行变。

\setsansfont 保持鸿蒙 —— 标题靠 \hm 切到 OUCHM 族,西文 sans 位仍是鸿蒙,
标题的中西文因此都是鸿蒙,与正文区分得开。

二、\hm 重定义为中西文一起切(cls/font.cls,本次核心)

这是「字体一会儿一个样」的真正来源。fonts.tex 里的 \hm 是
    \def\hm{\CJKfamily{OUCHM}}
纯 xeCJK 中文字族切换,管不到阿拉伯数字和拉丁字母。而标题、封面主标题、
摘要标题都用 \hm 表示「这是鸿蒙」,于是凡是标题里夹了西文就还是西文字体:

  · 章节编号 "1." "3.1" → 走 \setmainfont → 旧版是鸿蒙粗,改 Cochineal 后
    变成衬线粗,与中文鸿蒙粗并排
  · "这是一个很好用的 LaTex 模板" 里的 LaTex → 走 \setmainfont
  · 目录条目编号是数字、标题是中文 → 同一条目录两种字体

修法:本模板内把 \hm 重定义为 \hmlatin\CJKfamily{OUCHM},中西文一起切。
一次在源头解决,不在每个调用点补 \hmlatin —— 后者必然漏(封面、摘要、
目录标题、页眉、文本框标题各漏一次,本次实测漏了 4 处)。

不改 ../fonts.tex 的 \hm:幻灯片和简历也在用,它们没有这个问题,全局改
会外溢。

三、目录条目与页码归零(cls/title.cls)

\cftsecfont 等三条只管条目文字,页码走 \cft*pagefont,不显式清掉的话
目录里页码比标题还粗、最抢眼。两组共 6 条一起设 \normalfont。
不塞 \bfseries:加粗与否是各条目录自己的事,硬加会让二三级也变粗。

四、代码等宽位换 Latin Modern Mono(cls/font.cls)

旧版 \setmonofont 也是鸿蒙 —— 它不是等宽字体,代码里 i/l/1、m/w 宽度
不一,竖向对不齐、缩进看着是歪的。lmmono 是 TeX Live 自带,无需额外
字体文件。

⚠️ 这里不能用 Extension + UprightFont=*-regular:lm 系列文件名本身是
"lmmono10-regular.otf" 已带 -regular,再拼会变成 lmmono10-regular-regular
然后报 cannot be found。给完整文件名、不给 Extension。粗体用
lmmonolt10-bold(同族等宽,换粗体不错位),没有 lmmonobq 这个变体。

五、内容块保留 3 个 Underfull(cls/boxes.cls,只加注释不改代码)

第 208/214/220 行的 \verb|Illuminate\Foundation\Http\Kernel| 是 35 字符
不可断串,在内容块 371pt 内宽里塞不下。试过无效的:\emergencystretch
2em/10em(不是额度不够,是这行没有足够可拉伸 glue)、\sloppy(badness
从 1231 升到 3590,更差)。有效但不采用:\seqsplit(归零但任意字符处
断行,代码路径被切两段)、窄体 lmmonoltcond(归零但压缩可读性)。

结论:保留这 3 个,badness 1231 属轻微(10000 才是严重),渲染只是行末
留白略多。日志里看到它们属预期,不是回归。

六、report.tex 字体说明同步

第 52/58 行原文说「英文字体默认使用鸿蒙」,改后已不准确,重写为
Cochineal + Latin Modern Mono 的实际状况,并说明标题编号统一的原因。

验证(两套环境各跑两遍,逐字同数)

  WSL / TeX Live 2025:rc=0,error 0,Overfull 0,Underfull 4,10 页
  Windows / TeX Live 2022:rc=0,error 0,Overfull 0,Underfull 4,10 页

pymupdf 提取字体分布,两侧完全一致:
  Cochineal-Roman 782   OUCSerif-Regular 143   LMMono10-Regular 98
  OUCKai-Regular 33     HarmonyOS_Sans_SC_Bold 22   HarmonyOS_Sans_Bold 14
  OUCSerif-Bold 8       FontAwesome 5   HarmonyOS_Sans_SC 3
  ZhuqueFangsong 2      OUCSans-Regular 2   CMSY10 1   CMEX10 1
  HarmonyOS_Sans 1

标题逐页核对(中西文双档均属鸿蒙):
  p1 封面   HarmonyOS_Sans_SC_Bold「这是一个很好用的」+ HarmonyOS_Sans_Bold「LaTex」
  p2 目录   HarmonyOS_Sans_SC_Bold「目录」
  p5 摘要   HarmonyOS_Sans_SC_Bold + HarmonyOS_Sans_Bold「LaTex」
  p6 正文   HarmonyOS_Sans_Bold「1.」+ HarmonyOS_Sans_SC_Bold「准备工作」
  p10 正文  HarmonyOS_Sans_Bold「8.」+ HarmonyOS_Sans_SC_Bold「图标」

OUCSans-Regular 2 / ZhuqueFangsong-Regular 2 / HarmonyOS_Sans 1 三处少量
命中已逐个查清,都不是回归:
  · p6「黑体」「仿宋」—— 正文故意演示 \fzzdx / \fzfs 的示例文字
  · p8 每页同 bbox、45° 旋转、29.8pt —— 全页水印,设计如此
  · p10「HTTP/Console」—— 文本框标题走 fonttitle=\hm,改后已是
    HarmonyOS_Sans + HarmonyOS_Sans_SC,中西文都属鸿蒙

涉及文件:
  科技报告/cls/font.cls    默认族、\hm 重定义、等宽位
  科技报告/cls/title.cls   目录条目与页码归零
  科技报告/cls/boxes.cls   仅补 Underfull 记录注释,代码未改
  科技报告/report.tex      字体说明文字同步
2026-10-29 15:47:33 +08:00
laoyang 8660860495 build.sh 两处输出打磨 #18
1) 页码那行改为原样输出。原先用正则截断到 "page",把结尾的括号吃掉了,
   打出来是 "1 page" 而不是 "(1 page).",看着像少字符。

2) 临时文件改用 ./.build_out.$$ + trap 清理,不再用 mktemp。mktemp 在
   Windows 的 Git Bash 里返回 /tmp/... 形式,随后的 rm 会触发安全检查
   (SAFE_DELETE_INVALID_PATH: embedded drive prefix is not allowed),
   无害但会往输出里插一行噪音。

3) 取回成功后打印的路径转成 Windows 形式(D:/...),不再显示 Git Bash
   的挂载路径(/d/...)。
2026-10-29 12:03:02 +08:00
laoyang ef1bc72603 加入 WSL 编译取回脚本与换行符策略 #18
build.sh      在 WSL 内编译(默认 xelatex),成功后用 scp 把 PDF 取回
              Windows 侧同路径。支持单模板与 all 全库。路径全部走环境
              变量覆盖,默认值可用,不硬编码某个人的目录。

verify_all.sh 批量编译验证全库主文件,打印 error / Overfull / Underfull
              与页数。每个模板都在自己目录下编译 —— 模板的 .sty 与
              ../fonts/ 是相对编译工作目录解析的,从仓库根调用找不到字体。

.gitattributes 把所有 .sh 钉成 eol=lf。Windows 侧 core.autocrlf=true 会把
              脚本存成 CRLF,到 Linux 上执行就报
                  /bin/bash^M: bad interpreter: No such file or directory
              这个错误容易误判成"没装 bash",所以在仓库层面固定规则,
              不依赖各人本机的 autocrlf 设置。.tex/.sty/.cls 同样钉 lf,
              避免中文注释行尾残留 CR 被 XeTeX 当字符排出来。

关于脚本为什么要写成「编译-取回」而不是纯编译:
WSL2 会按空闲把整个虚拟机 poweroff,届时 xelatex 连同 PID 1 一起消失,
/tmp 也一并清空(后台日志丢失)。脚本的 ssh 会话在编译期间保持不断,
顺带起了保活作用,所以不要把它改成后台运行。
2026-10-29 12:01:06 +08:00
laoyang 1c27041c71 简历:babel 选项 frenchb 改为 french,兼容 TeX Live 2025 #18
frenchb 是 babel 早期的法语方言名,TeX Live 2025 已把它从「已知语言」
列表里移除,写旧名会报 Unknown option 'frenchb',压住后还会进一步炸在
\begin{document} 处的 \bbl@main@language。改成 french 在旧版本上同样可用,
是向前兼容的写法。

本模板正文是中文,babel 这里只影响西文连字与断词细节,中文断行由 xeCJK
负责,因此改动不影响排版结果。

顺带记录:本次在 WSL(Ubuntu 26.04 + TeX Live 2025)内首次跑通全库 13 个
主文件的编译验证,页数与 Windows 端(TeX Live 2022)一致。另有两处
Linux 侧环境差异不属于模板问题,已在工单 #18 里说明处理方式:
FontAwesome.otf 不随 Debian 的 texlive 分发(用 fontconfig 注册仓库内字体解决)、
简历另需 texlive-lang-french。
2026-10-29 11:59:43 +08:00
laoyang 7cd542a11f 克隆地址改回真实 code 地址 #17
上一轮脱敏时把 clone 地址一并换成了 example.org 占位,属过度处理。
code.yangyq.net/laoyang/ouc_latex_template.git 是当前项目的真实地址,
是「用户从哪 clone」的功能信息,不是隐私,改回。

真名「杨永全」与个人账号「dryangyq」的清除不回退。

slides.tex 脚注里的 URL 需转义下划线(ouc\_latex\_template),否则
报 Missing $ inserted;README 是 markdown 不用转义。

验证:slides 重编 0 error / 30 页,PDF 脚注为真实地址、无 example.org 残留。
2026-10-29 08:35:25 +08:00
laoyang e70339fcf6 全库脱敏:清除真实姓名、个人账号与私有域名 #17
开源前排查,发现三处真实个人信息残留,全部清除:

1. 真名「杨永全」→ 中性署名「中国海洋大学 LaTeX 模板库」
   幻灯片/ 下 6 个 sty 文件头的「%% 作者:杨永全」。

2. 个人账号 dryangyq → 占位地址
   幻灯片/slides.tex 第 66 行脚注里的 github/gitee/gitlab 三个
   dryangyq 仓库地址,改为 example.org 占位并注明开源后替换。

3. 个人域名 yangyq.net + 私有 Gitea 账号 laoyang → 占位地址
   幻灯片/README.md 与科技报告/README.md 的 clone 地址
   code.yangyq.net/laoyang/... 改为 example.org 占位。

另重编幻灯片/slides.pdf:旧 PDF 的脚注里还印着 dryangyq 与
yangyq.net 的 URL(源码改了但成品没重编),逐字提取确认后覆盖。

验证:
- 全库源码(.tex/.sty/.cls/.md)grep 杨永全 / dryangyq / yangyq /
  yongquan / 永全 全部零命中
- 全库 PDF 成品用 pymupdf 提取渲染文本,上述关键词零命中
- 幻灯片重编 30 页、0 error

未处理(遗留,需另决策):git 历史 27 个 commit 的作者签名是
「laoyang <i@yangyq.net>」,含个人域名邮箱。若推到公开平台需
git filter-repo 重写历史(改全部 SHA + force push),属破坏性操作,
本单不做。
2026-10-29 08:17:08 +08:00
laoyang 1abb3cf5ef 特殊事项说明表示例文案换为浮标维护场景 #16
原 \sxdesc 示例是「去菏泽做项目研讨与系统演示、自驾」,用户要求换掉。
改为「渤海湾生态环境监测浮标例行维护,前往昌邑近岸观测站更换传感器
并回收监测数据,该站位于滩涂养殖区公共交通无法抵达,需随车携带
备件箱、采样冷藏箱与工具,故自驾前往」。

选这段的理由:保持原示例「为什么必须自驾」的两条必要性(公共交通不便 +
携带专用设备),只把事由换成本课题范畴内的真实场景,示范作用不变。

影响面:仅 \sxdesc 一个宏,未动任何排版代码。

验证:
- xelatex 0 error / 0 Overfull / 0 Underfull / 1 页
- 四条横线 y = 172.99 / 457.49 / 516.34 / 573.64,与原件逐点一致
- 描述仍为 2 行(227.81 / 241.49),签名区、备注区、页码坐标全部未变
  说明 \vfil 正确吸收了文案长度变化,这正是本模板相对原 docx
  「8 个手写空段」的核心改进
2026-10-28 19:50:37 +08:00
laoyang 0fd6021b03 新增特殊事项说明表 LaTeX 模板 #16
把报销用的《中国海洋大学特殊事项说明表》Word 版复刻为 LaTeX 模板,
新增 特殊事项说明表/ 目录,与库内其余模板同一套约定。

三处关键设计:

1. 版心取「表格宽度」而非 docx 版心。原表 169.54mm 比 docx 版心宽
   13.54mm,靠 tblInd 负值顶出去;照搬 docx 版心必然 Overfull。
   改把 geometry 的版心直接设成表格宽度,零 Overfull 且位置逐点相同,
   代价是标题/备注需额外偏移补回 docx 版心的中心。

2. 行距不用 \baselineskip。本表行距逐行不同(10.5pt 与 12pt 混排),
   而 \baselineskip 只在同一段落内管行距 —— 每行 \par 自成一段后它
   根本没被读到(实测所有行距被压成 13.51,整表矮 2.25bp)。
   改成逐行插 \kern:基线距 = 上盒深度 + \kern + 本盒高度,
   与字体度量彻底解耦。

3. R0 改成「上下两半 + \vfil」,删掉原件那 8 个手写空段。
   描述写长写短都不再影响签名区位置,比原件更稳。

顺带记录六个实测踩出来的坑(块首行胶被丢弃、负 \kern 不能挡、
多行段 \ht 参照末行基线、\prevgen 必须在 \par 之后且在盒内取、
\vbox to N 的深度另计等),详见 sty 内注释与 README。

验证:
- xelatex 0 error / 0 Overfull / 0 Underfull / 1 页
- 与 Word 导出 PDF 逐项对齐:33 个文字元素 dY 全部 0.00bp,
  dX ≤ 0.04bp;四条横线与页码 0.00bp
- 像素差分 3.03%,全部落在字形轮廓上,无整体错位
- 全库 12 个模板回归通过,既有 11 个 PDF 零字节变化

与原件仅 3 处有意差异:字体换本库 OUC Serif(可分发)、
标题小标宋换真粗体(商业字体不可分发)、第 3 条备注编号统一对齐
(原件是手打漏配编号,偏 0.36bp)。
2026-10-28 19:09:12 +08:00
laoyang 389ddf51f0 README 引号统一为中文引号 #15 2026-10-27 15:05:33 +08:00
laoyang ecfbcb8c67 简历软著/转化/教研改为全自动统计,README 补使用说明 #15
新增 cvlist 环境:进入环境后每个 \item 自动 +1,条目里一个标记都不用写。
三节各只改两行(itemize → cvlist{类别}),删掉全部 15 处 \cvmark。

  \begin{cvlist}{软著}
    \item 某某系统. 2024SR9999901. ...
  \end{cvlist}
  概述:登记软件著作权 \cvnum{软著} 项

实测:加 1 条 → 概述自动 5→6;删 2 条 → 自动 5→3;还原 → 回 5。
版面与基线逐行完全一致(66/75/34 行)——cvlist 内部就是普通 itemize。
普通 itemize 不受影响(实测 3 条子项未被误计)。

专利、科研项目仍用逐条 \cvmark:它们一条要算两个类别
(专利+第一发明人、科研项目+主持/负责),cvlist 一次只能管一类。

README 新增「先回答一个最常问的问题:它是全自动的吗?」用表格直接回答
三种写法的差别,并补「全自动写法」「半自动写法」「加一个全新的类别」
三个小节,含可直接抄的代码。

踩坑:\cvmark 内部用 \detokenize 处理类别名,传参前必须 \expandafter
展开 \cv@listcat,否则写进 .cvnum 的是字面串 "\cv@listcat"。

验证:0 error / 0 Overfull / 0 Underfull,3 页;全库回归与基线一致。
2026-10-27 15:04:48 +08:00
laoyang eb3b53946c 简历概述的成果数字改为自动统计(列几条算几条) #14
概述原来手写「论文 40 余篇、专利 20 余项」,每次增删条目都要回头改。
改为正文标记、概述取数:

  \item ...论文... \cvtagcount{SCI}     % 显示 SCI 并计数
  \item ...软著... \cvmark{软著}        % 只计数
  概述:论文 \cvnum*{SCI,EI,核心} 篇(SCI \cvnum{SCI} 篇)

共注册 11 类:SCI/EI/核心/专利/第一发明人/软著/科研项目/主持/负责/转化/教研。

关键技术:不用 aux,改独立数据文件 \jobname.cvnum。
中文键经 aux 往返后 \ifcsname 全部失效(xeCJK 把汉字设为活动字符,
键的 token 形态不一致;ASCII 键正常);独立文件里中文键完全正常。
累加与显示分离(cvacc@ 每遍从 0 起 / cvnum@ 读自上一遍),
否则概述在正文之前会让上一遍的值被本遍叠加,数字翻倍。

踩坑:\cvmark 不能放 \experience 的关键词参数(会被 \foreach 拆开,
报 Misplaced \omit),必须放描述参数内;也不能放 longtable 单元格之外。

验证:0 error / 0 Overfull / 0 Underfull,3 页;加标记后版面与基线
逐行一致;连续 5 次编译数字稳定;增删条目后数字自动跟随。

⚠️ 口径变化:自动统计只数列出来的条目。示例原来写「40 余篇」但正文
只列 9 篇代表作,改成自动后变「9 篇」。README 已写明这两种口径的区别。
项目总经费仍手填(\experience 无经费字段)。
2026-10-27 14:56:34 +08:00
laoyang 8e3017f359 简历左上角加中国海洋大学校徽(可选,默认不印) #13
新增 \cvlogo[<文件名>]{<宽度>},默认不调用、不出现,不影响现有版面。

- cls:导言区只登记参数,真正画图挪到 \makecvheader 开头的 \@makecvlogo,
  否则导言区产生内容报 Missing \begin{document}
- 定位用 tikzpicture[remember picture, overlay] + current page.north west,
  距纸左 10mm / 距纸顶 6mm(相对纸边,不随页边距变)
- 距顶不照搬科技报告的 20mm:简历页边距 15mm、姓名墨迹顶 17.2mm,会压到姓名
- tikzpicture 即使全 overlay 仍占一行 17pt,用 \vspace*{-17pt} 抵消;
  \smash / \hbox to 0pt / \vbox to 0pt 三种写法实测都消不掉
- 尺寸定 28mm(横式 2400:605 ⇒ 高 7.06mm),是 15mm 边距下的上限附近

实测:logo 28.00×7.06mm,x=10.07mm、y=6.07mm,下沿 13.1mm;
姓名 y 保持 48.8pt 未位移;3 页 0 error / 0 Overfull / 0 Underfull / 0 个 ×。
体积 158KB → 573KB(内嵌 2400px 原图,实际只用 28mm≈660px)。
2026-10-27 14:25:27 +08:00
laoyang 69da5b41a6 简历排版修正:项目经验整块右移、西文换 Cochineal、课程执行大纲漏网 × #12
一、项目经验整块右移(简历/awesome-source-cv.cls)
  \rightcolumnlength 算早了:geometry 的 1.5cm 边距要到导言区结束才生效,
  cls 里那句 \setlength 读到 article 默认 \textwidth=345pt,算出 249.87pt,
  比应有的 417.02pt 少 167.15pt。longtable 把窄表居中排,整块右移 83.6pt。
  修法:计算挪进 \AtBeginDocument 并减去 | 竖线的 \arrayrulewidth;
  R 列由 >{\hfill}m{2.5cm} 改为 >{\raggedright\arraybackslash}p{2.5cm}。
  日期左边缘 145.1 -> 48.5pt,与其余章节严格对齐。
  这类错误零 error 零 warning,只能量 PDF 坐标才能发现。

二、西文换 Cochineal(fonts/cochineal/ + fonts.tex + 简历 cls)
  中文思源宋体配 Termes 时西文笔画偏细,中英混排会「陷进去」。
  Cochineal 宽 225.42pt vs Termes 229.68pt,只窄 1.9%,断行位置基本不动;
  Pagella/XCharter 宽 7~11%,会把全库断行推着变,故不选。
  字体 920KB 入 fonts/cochineal/(SIL OFL 1.1,附 OFL.txt),
  fonts.tex 新增 \oucUseCochineal 开关,只简历调用,其余 10 个模板不受影响。

三、换字体后暴露的真实缺陷
  西文窄 1.9% 让断点整体前移,ICIEA 那条论文冲出 88.49pt(文字顶到纸边)。
  根因是中文紧跟英文的位置不是断开点,整串被当长单词。
  加 \emergencystretch=3em 解决。

四、课程执行大纲漏网占位符(ouccourse.sty)
  ××学部××学院 硬编码在 \ccschool 里,#11 只扫了 .tex 没扫 .sty 所以漏了。
  拆成 \ccdepartment / \cccollege 两个名称宏,默认「信息科学与工程学部 /
  计算机科学与技术学院」。重编后全文 × 归零。

「代码库 PDF 没更新」经核实不成立:本地/远程 HEAD 均为 8984b93,
从服务器下载 8 个 PDF 逐字节比对全部一致,简历.pdf 3 页 0 个 ×。

验证:简历 3 页 0 error/0 Overfull/0 Underfull;全库 12 项编译回归与基线一致。
2026-10-27 13:13:54 +08:00
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
laoyang cc0dfb7257 新增个人简历模板(简历/),字体全部换成仓库自带的 #10
从个人目录的中文简历迁移为第 11 个模板,三处字体重做:

1) 字体三层依赖全部拆掉
   - 删 zh_cn-adobefonts_external/internal.sty(Adobe 宋/黑/楷/仿,56 MB,
     商业授权不可分发),中文字体改由 ../fonts.tex 提供
   - awesome-source-cv.cls 的 localFont 分支(SourceSansPro 9 个 .otf)
     整段删除,西文改走 ../fonts.tex 的 TeX Gyre Termes
   - fontawesome.sty 原按字体名找系统 FontAwesome,改成显式
     Path=../fonts/fontawesome/,并把 FontAwesome.otf 收进仓库

   顺带修掉一个设计缺陷:原 adobefonts 里 BoldFont/ItalicFont/SmallCapsFont
   全部指向 Regular,等于加粗不变、斜体不变。现用字体自带的真粗体。

2) 占位化:真实姓名/手机/邮箱/住址/出生年月/论文题名与 DOI/专利号/
   软著号/33 条获奖全部改为 ××× / 20××;真人照 a.jpg/a.png 换成
   PIL 生成的 400×400 中性剪影 photo.jpg

3) 排版修正
   - 左栏宽度改为 \dimexpr\linewidth-\leftcolumn-4\tabcolsep\relax 自适应,
     修掉长表格 Overfull 4.48pt(原来没把 4 个 \tabcolsep 算进去)
   - 抬头两处 \vspace*{...}\\、\smallskip\\ 改为 \\[...],
     修掉 Underfull \hbox (badness 10000)
   - \socialinfo 末尾多余的 \\ 去掉

fonts.tex 的改动(全库共享):\textsc 用的 sc 档改用
\DeclareFontShape{TU}{OUCSerif(0)}{m}{sc}{<->ssub * OUCSerif(0)/m/n}{}
做形状替换,而不是 SmallCapsFont 选项 —— 后者与本文件 ItalicFeatures 的
跨目录 Path 互斥,任何写法都报 The font "OUCSerif-Regular" cannot be found.

回归:11 个模板全部零 error 编译通过;科技报告/试卷/课程执行大纲
文本与改动前逐字一致,4 个既有 boxwarn 为改动前基线,未新增。

编译:cd 简历 && xelatex 简历.tex 跑两遍,3 页,零 error/Underfull/Overfull。
嵌入字体仅 OUCSerif-{Regular,Bold}、TeXGyreTermes-{Regular,Bold}、FontAwesome。
2026-10-27 11:17:24 +08:00
laoyang 95afc9caa6 成绩构成说明:表格格线全画 + 签字栏去掉年份占位 #9
用户反馈:中间表格要把线都画上,中间空白容易看错行;最后的年月日
也不要带 20xx。

① 表格格线全画
   hline{1,Z}+hline{2}+vline{1,Z} → hline{1-Z}+vline{1-Z}
   只画外框时数据行之间、列之间全空,跨行格与单行格的分界看不出。

   连带必须改列宽:画上 5 条内部竖线后表宽多 2.5pt,报
   Overfull 2.47554pt,末列 30.28mm → 29.40mm 补回。

   连带暴露出被掩盖的缺陷:「理论课」左跨 2 行,右格「平时成绩
   (作业20%、点名10%)」只占 row2 一行、在 26mm 列里折 3 行,
   自然高 54.73pt —— row2 被撑到 54.73pt,文字上下零留白,末行
   「10%)」墨迹底离行线仅 0.90pt(0.32mm),其他行是 4.97pt。
   画满格线前那里本来没有线,缺陷完全看不到。

   治法 row{2}={ht=22mm}。关键是 ht 为最小高度、须大于内容高才生效:
   先试 12.5mm(35.4pt < 54.73pt)无反应,22mm(62.4pt)才把行撑到
   62.86pt,末行墨迹间隙 4.08pt(1.44mm),与其他行同量级。

② 签字栏去掉年份
   20××~年 月 日 → 年 月 日。签名文件的年份由签字人当场手写,
   模板预留占位符反而占掉手写空间。

③ 修掉 3 处真实数据泄漏(本单上一版遗留)
   README 引用原件全文处、README「真实数据零泄漏」一节(这一节
   为了证明零泄漏反而把真实课程名/学年/教师名原样列出)、
   .tex 的「闭卷笔试」。已复查 10 个关键词零命中。

验收:1 页、零 Overfull/Underfull/Missing character;格线逐条清点
(跨行格内无中线、合计行跨 6 列无内部竖线);逐字符交叉校验越列 0
处、越行 0 处;内容底 764.71pt vs 版心底 769.89pt,余量 5.18pt。
2026-10-27 09:45:58 +08:00
laoyang a29f193cff 新增成绩构成说明 LaTeX 模板(成绩构成说明/) #9 2026-10-27 09:15:58 +08:00
laoyang a4589139da 教学日历删掉表格末尾的「课程考核及评价方式」行(另有独立成绩构成说明) #8 2026-10-27 09:15:54 +08:00
laoyang 88b3e088d6 签字栏去掉年份占位符,只保留手写填空位「年 月 日」 #8 2026-10-27 08:55:30 +08:00
laoyang 3b67659689 修复签字栏年月日重叠:年份改用定宽右对齐盒子 #8 2026-10-27 08:48:17 +08:00
laoyang 25dc872062 新增课程教学日历 LaTeX 模板(课程教学日历/) #8
把学校下发的通用空白表「附件3:中国海洋大学课程教学日历(理论课程)」
做成 XeLaTeX 模板,与 试卷归档封面/、试卷归档目录/ 同一套做法。

版式按原 .doc 逐项还原并实测标定:
- 表宽 174.625mm(tblW 9900 twips),tblInd 为负(−13.97mm),
  表格比版心更靠左,可见左边界 15.875mm
- 7 列宽度取 gridCol − 2×colsep − 线宽
- 边框 0.5pt(w:sz=4),内边距 1.905mm(108 twips)
- 字号 14 / 12 / 10.5bp 三档,全部用 bp(Word 的 pt 是 PostScript pt)
- 行高按「行数 × 23pt」显式给 ht(原件 w:line=460 exact)

实测校验(pymupdf 读两版 PDF):
- 8 条竖线 x 偏差 ≤ 0.004mm
- 纵向锚点:附件号 / 标题 / 表格顶线 Δ = 0.00pt,其余 ≤ 0.03pt
- 行高 18 行中 17 行 Δ ≤ 0.4pt
- 字号 14.00 / 12.00 / 10.50 精确
- 零警告(无 Overfull / Underfull / 缺字)

真实数据零泄漏:原 .doc 是填过的实例,模板把所有字段换成占位符
(××××、000000000000、×、20××),已 grep 确认课程名、开课号、
教师姓名、年份、16 周日期与章节名均零命中。

README 记录五类坑:bp 单位、固定行距在 TeX 里不等于 baselineskip、
linespread 必须在 fontsize 之后、SetCell 的 c 列不折行、leftskip 与
geometry 叠加;以及原件五处不一致(第一周行距 15.6pt、周次列对齐
前后不同、表头折行数、表头不加粗、签字栏用空格顶位)。

注:本模板 3 页,原件 2 页 —— 因不复制第一周行距的疏漏,该行多 22pt。
2026-10-27 08:37:28 +08:00
laoyang 8fa44b138c 新增试卷归档目录 LaTeX 模板 #7
把「附件2:信息科学与工程学院归档目录(理论课).doc」做成 LaTeX 模板,
落在 试卷归档目录/。版式逐项照原 .doc 还原,尺寸全部注明换算过程。

- oucgddir.sty:A4、表宽 150.81mm、13 行固定行高、单元格宏
- 试卷归档目录.tex:12 项核对清单
- README.md:用法 / 版式参数表 / 实测数据 / 踩坑记录
- 根 README.md、fonts.tex:模板清单加一项,「七个」改「八个」

与原稿实测对比(pymupdf 读 PDF):
  表格竖线 x Δ ≤ 0.001mm,横线 y Δ ≤ 0.006mm
  32 行文字水平中心 Δ ≤ 0.11pt,字号 24/18/12/10.45 全部精确
  编译 1 页,零 Overfull / Underfull / 缺字

踩到并解决的五个坑:
  1. \fontsize 必须用 bp(TeX pt 比 PostScript pt 大 0.36%,24pt 实测 23.91)
  2. xeCJK 吞连续半角空格 → 标题字间用 \gdgap 手动 kern 24bp
  3. xeCJK 默认 PunctStyle=quanjiao 会挤压全角括号,使含括号的行整行
     右移 4.23pt → 必须 \xeCJKsetup{PunctStyle=plain}
  4. tabularray 把线宽算进列宽、ht 不含 hline 线宽、boxes 比 Σwd 多
     0.4945pt → 三处都要实测标定
  5. 单元格整体下移只有「尾部 \vspace*」有效,顶部 \vspace*/rule 会被
     首行 ascent 吃掉,\raisebox 被 m 居中抵销

字体:方正楷体_GB2312(商业,不可分发)→ OUC Kai(霞鹜文楷子集,OFL 1.1),
西文 Times New Roman → TeX Gyre Termes。字宽逐字相同(60.00 / 120.00pt 全等)。
2026-10-27 07:51:10 +08:00
laoyang 8aa979739a 字体统一:建公共字体目录,全部改用开源可商用字体 (#6)
七个模板原先分两套做法:幻灯片/fonts(49MB 鸿蒙 18 个字重)与
科技报告/font(92MB,含 5 款方正商业字体),其余模板直接调系统
SimSun/SimHei/KaiTi/FangSong/Times New Roman。换机器就编不出来,
方正系列也不允许随仓库分发。

统一到仓库根的 fonts/ + fonts.tex:
- OUC Serif(思源宋体 SC 子集)   —— 宋体
- OUC Sans(思源黑体 SC 子集)    —— 黑体
- OUC Kai(霞鹜文楷子集)          —— 楷体
- Zhuque Fangsong(朱雀仿宋)      —— 仿宋
- TeX Gyre Termes                  —— 西文 Times 等价(度量逐字相同)
- HarmonyOS Sans                   —— 幻灯片/科技报告原有字体

fonts.tex 是唯一允许声明字体的地方,7 个模板全部 \input 它。
字体体积 141MB -> 49MB(去掉重复),全库共用一套最小集合。

几处踩过的坑(均已写进源码注释):
- \newCJKfontfamily 与 ctex 默认 fontset 冲突会中断编译,改用
  \setCJKfamilyfont + \def
- \newfontfamily 缺粗体档会让 \bfseries 静默失效,四档必须全给
- UprightFont= 与主参数不能同时给,否则文件名被拼两次
- Path= 相对编译时工作目录,不是相对 .sty
- ×/□/○ 等符号按 Unicode 区段被判成西文,需 \xeCJKDeclareCharClass
- 中文斜体的 ItalicFont 与主字体不在同一目录,须在 ItalicFeatures
  里单独写 Path/Extension(否则报 OUCKai-Regular cannot be found)

顺带:
- 科技报告 report.tex 的字体演示正文改为新字体名(原文写着方正系列)
- 试卷归档封面新模板并入本库
- 科技报告 shell 命令框底色改海大蓝(#5 遗留)

验证(7 个模板 8 个 PDF 全量重编 + 逐行 A/B 对照):
- 错误 0,缺字 0
- 幻灯片 362 行逐行完全一致,零漂移
- 年度考核登记表 / 劳务发放说明表 / 试卷题型示例 / 参考答案 文本完全一致
- 课程执行大纲 仅 2 处断字连字符差异(throughout、processing),
  1 条 6.39pt Overfull 已论证不可见(距纸张右边缘仍有 20.7mm)
- 科技报告 内嵌字体方正归零,只剩 OUC Serif/Sans/Kai + Zhuque
- 全库正文 857 个非 ASCII 字符,四款中文字体(含粗体)覆盖 100%
2026-10-27 00:43:14 +08:00
laoyang c69f4461dc 科技报告配色统一为幻灯片同一套海大标准色 #5
改前用的是 xcolor 通用色,跟海大无关:notebox 用 NavyBlue、importantbox
用 Orange、代码关键字纯蓝 rgb(0,0,1)、注释纯绿、代码标题 violet、水印纯灰。
同一个学校两个模板的「蓝」和「红」不是一回事。

新增 cls/color.cls 作为唯一配色入口:
- 10 个基色与 幻灯片/theme/beamercolorthemeOUCSlide.sty 逐值相同
  (前 7 个是官方 2021 版 VI 标准色,后 3 个是幻灯片补充的第三色)
- 8 个语义词别名(oucprimary / oucaccent / oucinfo / oucalert /
  ouccaption / oucrule / ouclink / oucmuted),按语义引用而非色名,
  将来调色只改一行
- 代码配色从标准色派生:关键字→海大蓝、注释→苍松绿、
  字符串→海大红、类型→海大天蓝、边框→专银

各文件改为引用语义色,不再硬写 RGB:
- boxes.cls:notebox NavyBlue→oucinfo,importantbox Orange→oucalert
- code.cls:删掉本地 5 个 definecolor;bashstyle NavyBlue→oucblue;
  bashoutputstyle black!10→codecolorbg + 专银线;行号 gray→oucmuted;
  代码标题 violet→ouccaption
- hyperref.cls:硬写 black→ouclink
- setting.tex:水印纯灰→海大蓝 4%(原 Lightness 会强制切 gray 模型覆盖颜色,已去掉)
- report.cls:加 \input{cls/color.cls},必须有在 boxes/code 之前

有意保持中性的两处(已在注释里说明理由):
- shellbox / invertedshellbox:终端反白块语义就该是黑底,
  换成蓝会变成「强调块」抢正文注意力
- 页眉线:彩色页眉线会跟正文海大蓝标题抢视觉层级,仍 0.5pt 黑

验证:错误 0,10 页,Overfull 0,Underfull 保持既有 2 条;
PDF 逐 span 提取文字色只剩 #004098 / #C81528 / #000000,
矢量填充与描边全部落在标准色内,无 NavyBlue / Orange / violet 残留。
2026-10-26 22:50:19 +08:00
laoyang 62649ef6d6 科技报告封面加校徽:补入 logo 素材与 cover.tex 改动 #4
上一提交只带进了 logos/README.md,图片与 cover.tex 因暂存顺序问题漏掉,
此处补齐。改动内容与前次提交说明相同:
- 新增 10 张官方 VI 校徽 PNG(横式 4 + 方形 6)
- cover.tex 加 \coverlogo,tikz current page 锚点定位在纸边
  内 20mm,宽 38mm,overlay 不占正文流
- report.pdf 重编,封面含校徽,10 页

验证:错误 0,10 页,Overfull 0,Underfull 保持既有 2 条。
2026-10-26 22:49:39 +08:00
laoyang 168f4bae5d 科技报告封面加中国海洋大学校徽(官方 VI 横式四色版)#4
位置:首页左上角,距纸左/纸顶各 20mm,宽 38mm。

用 tikz 的 current page 锚点相对【纸边】定位,而非相对正文框:
- overlay 使 logo 不占正文流,封面下方原有排版位置零变化
  (实测首条横线仍在 41.97mm,改动前后一致)
- 锚点绑在纸边,以后改 cls/geometry.cls 的边距不会让 logo 走位

参数依据:
- 距边 20mm:版心左边距 27mm,logo 再外伸 7mm「挂在页眉区」,
  同时留足 A4 印刷裁切余量(一般 10~12mm)
- 宽 38mm:官方横版比例 3.97,高约 9.6mm;logo 下沿距首条横线
  实测 12.32mm,疏密合适,不再额外加空

新增 logos/ 目录:官方 2021 版 VI 素材,10 张(横式 4 + 方形 6),
含 README 说明每张的适用场合与禁止改动的注意事项。

验证:错误 0,10 页,Overfull 0,Underfull 保持既有 2 条。
2026-10-26 22:49:32 +08:00
laoyang 1f807e9cce 所有模板目录改为中文名,并入幻灯片与科技报告两个仓库(#3)
目录改名(git mv 保留历史,包名不变):
  exam/   -> 试卷/
  form/   -> 年度考核登记表/
  form2/  -> 劳务发放说明表/
  course/ -> 课程执行大纲/

改名即可编译:实测 6 个模板在含中文的目录下 XeLaTeX 均零报错,
PDF 逐页文本与改名前的版本完全一致(0 页差异,仅元数据时间戳变化)。

并入两个此前独立维护的仓库:
  ouc-slide-latex-template  -> 幻灯片/
  ouc-report-latex-template -> 科技报告/
带入了 theme/ fonts/ logos/ figs/ cls/ input/ 与 fontawesome.pdf,
字体随模板附带(无须在系统安装)。中间文件一律不入库。

同步修正的文档:根 README 目录表改为中文名并说明统一维护;
四个子 README 的标题;ouclw.sty 注释里对 form/ 的交叉引用;
幻灯片与科技报告 README 里「从旧仓库 clone」「按年份切分支」等已失效的说明
(并入后只有 main 一个分支,各年份 TeX Live 通用)。

两个迁入模板的 PDF 保留源仓库原版(逐字节一致),未重新编译:
源 PDF 出自 TeX Live 2026,本机为 2022,重新编译会让结尾页装饰层定位
产生细微偏移,保留原版以保证样张与原来完全一致。
2026-10-26 18:31:04 +08:00
laoyang 6584dfac88 更新 course/ 编译产物(#2)
重新编译后 PDF 元数据(时间戳)变化,内容与上一版一致:5 页、零 Overfull/Underfull。

#2
2026-10-26 17:44:16 +08:00
laoyang d353aaa324 新增课程教学执行大纲 LaTeX 模板 course/(#2)
把学校下发的《本科课程教学执行大纲》Word 模板复刻为 XeLaTeX,
内容全部虚构(课程名、代码、开课号、教师、教材、思政案例)。

- ouccourse.sty:版式宏包,尺寸全部从 OOXML 量出
  · 页面:左 27.52 / 右 22.93 / 上 25.05 / 下 4.94 mm(照抄原文件的不对称与极小下边距)
  · 表 0:156.93mm,5 行 × 8.01mm,两列 131.921/25.012mm
  · 表 1:165.54mm(超版心 5.91mm,居中溢出),6 列逐列对齐 gridCol
- 课程执行大纲.tex:虚构课程「信号与系统基础」完整示例,5 页
- README.md:用法、参数表、twips→mm 对照、字体降级、六个坑、校验方法
- 根 README.md 目录表补 course/ 一行

关键技术点(README 有详述):
- 表宽 > 版心时不能按比例缩列宽(会让长文字提前折行),要用 \leftskip 整块左移;
  \hspace* 对 longtblr 的 \halign 盒子无效
- tabularray 的 wd= 是内容宽,不含竖线自身 0.5pt;ht= 含横线预算
- presep/headsep 是 outer 键,误写进 inner spec 会把 "0pt" 印成垃圾文字且不报错
- 表级默认字号须写 cells={font=...},单独写 font= 被静默忽略
- longtblr 跨页提示要清两组模板;*-text 不能设 empty(会报 LaTeX3 变量错误)
- ctex 默认 \linespread≈1.3 会覆盖 \fontsize 的行距

验收:26/26 项量化达标,编译零错误零 Overfull/Underfull,5 页
2026-10-26 17:43:50 +08:00
laoyang e032aec228 新增劳务发放说明表 LaTeX 模板(form2/)#1
把实验室《劳务发放说明表》docx 复刻为 XeLaTeX 模板,与 exam/、form/ 同一套做法:
自包含子目录、版式逐项对齐原 docx、模板不含真人信息。

- form2/ouclw.sty      版式包:A4 + left=31.70mm + 表宽 150.32mm,
                       4 列 / 5 行、14pt 宋体、15.6pt 行距、0.5pt 边框、
                       1.905mm 单元格内边距,全部尺寸附 twips→mm 换算注释
- form2/劳务发放说明表.tex  主文件,填表只改 4 个变量
- form2/README.md      用法、换算表、四个坑、量化校验方法与实测数据
- README.md            目录表登记 form2/

文字改写:原文「聘请秦依康等2位研究生参与《观测数据驱动的渤海生态系统健康
评估关键技术研发》项目的研究工作。」改为「聘请xxx等x位研究生参与《xxx》
项目的研究工作。」,句式未动;其余内容一律 × 占位。

量化验收(pdftocairo -svg + pdftotext -bbox):
  表宽 150.137mm(目标 150.319,差 -0.18)
  表左  31.662mm(目标  31.700,差 -0.04)
  R0 11.172 / R1 5.668 / R2 49.646 / R3 22.159 / R4 11.172 mm 全部达标
  三个签字格标签基线、日期行基线完全重合
  编译零错误、零 Overfull / Underfull,输出 1 页

本次踩到并记录在 README 的四个坑:
1. ctex 默认 \linespread≈1.3 会把 \fontsize{14}{15.6} 放大成 20.28pt
2. 合并格 {c} 是 LR 模式,不折行而是撑宽整表;\hsize 也未重设
3. 合并格内容可用宽要补回 2*colsep*(n-1),否则长文本提前折行
4. \parbox[t] 与 tabularray 的 strut 叠加会每行多出 3.6pt
2026-10-26 16:18:58 +08:00
laoyang 565ec7c505 add form: 教职工年度考核登记表 LaTeX 模板
按学校下发的 Word 表逐项复刻,尺寸全部从 docx 的 OOXML 数值换算
(twips→mm/pt),不含真人信息。

- form/ouckhtb.sty          版式包:页面/字体/11 列宽/9 行高/表格环境
- form/年度考核登记表.tex   主文件:占位数据 + 表格 + 年度总结
- form/README.md            用法、版式数据来源、四个排版坑、校验方法

关键排版结论(sty 内均有注释):
- 合并格 cell{r}{c}={c=n}{c} 的 {c} 是不折行的 LR 模式,文字超宽会
  把列撑宽、整表超出版心(实测 448pt→559pt),故合并格一律包
  \khtbfit{跨度宽}{文字}
- 合并格里 \hsize 未被重设,长文本须用定宽 \parbox
- 跨度声明只有 {c=n}{c} 一种写法
- colspec/row{} 不能放宏(Unexpandable command)
- longtblr 须 stretch=0,且要清空四个 caption 模板去掉「表 0」

校验:零 Overfull/Underfull,2 页,表宽 157.96mm(目标 158.33mm)。
2026-10-23 12:01:32 +08:00
laoyang 47158f2add add exam: 试卷与参考答案及评分标准模板
- exam/oucexam.sty    试卷版式包(195x270mm 专用试卷纸)
- exam/ouckey.sty     答案与评分标准版式包(默认 A4,可选 exampaper)
- exam/试卷题型示例.tex        16 类题型,6 页
- exam/参考答案与评分标准示例.tex  8 大题 / 满分 100,3 页
- exam/README.md      用法与书写注意事项
- .gitignore          忽略 LaTeX 编译中间文件
2026-10-22 16:27:54 +08:00
laoyang c70c063915 Initial commit 2026-10-22 08:15:07 +00:00