Commit Graph
4 Commits
Author SHA1 Message Date
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 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 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