﻿---
title: 能否用 Typst 写 UESTC 毕业论文：可行性调查与踩坑记录
excerpt: 写毕业论文时，我不想再用 Word 排版了。Typst 看起来是个优雅的替代方案。本文记录我对提交要求的核实、模板的使用、VS Code 的配置，以及 PDF 转 DOCX 的踩坑过程。
tags:
  - AI
  - Typst
date: 2026-04-25
---

<script data-swup-reload-script type="module" src="/js/components/tab.js"></script>

<script data-swup-reload-script type="module" src="/js/components/sidenote.js"></script>

<style>
.latex {
  font-family: var(--font-serif);
  font-style: italic;
}

.latex .a {
  position: relative;
  top: -0.35em;
  font-size: 0.7em;
}

.latex .e {
  position: relative;
  top: 0.15em;
}
</style>

## 为什么想用 Typst

### TL;DR

1. 不习惯 Word/WPS 的排版工作流
2. <span class="heimu">方便抽鞭子让 LLM 干活呗</span>

### The Frustrations of Formatting in Word/WPS

毕设等稍带严肃的论文，往往都有严格的格式要求。我并不排斥排版，它本身是一个带来熵减的愉悦过程，我也在这个博客的主题上花了不少时间打磨排版。

不过，作为一个还算年轻的程序员，接触了 Ruff、Biome 这类新生代格式化工具之后，很快就习惯了自动化带来的便捷。

所谓由奢入俭难，相信再晚几年出生的程序员，如果有一天要手动在操作符两边加空格、手动删除行尾空格，大概也会觉得痛苦。

Word 和 WPS 的用户体验比这更让人难受。Word 至今不支持多标签页，修改页眉页脚时几乎没有任何直观的反馈，经常牵一发而动全身；标题、图表和参考文献的编号，也常常沦为打断写作流的“体力活”。

### The Advantage of Markdown/Typst

早期写作时我用的也不是 Typst，而是 Markdown。它们共同的优势在于版本控制，以及更方便的 LLM 集成。LLM 带来的便捷已经属于“伟大，无需多言”了；版本控制则见仁见智，但它至少能减少“电脑关机但 DOCX 没保存”这种情况

随着写作需求的变化，我逐渐转向了 **Typst**。与 Markdown 相似，Typst 是一款现代化的排版工具，但它提供了更灵活的排版控制。比如，Markdown 中的表格功能就显得较为单一，不能合并单元格。

而 Typst 不仅能够处理这种排版需求，而且社区里有相对成熟的模板，把页眉页脚、图表编号、引用文献等工作都自动化了。Markdown 可以做到大致的功能，但它的语法有限，不能包揽论文写作的所有场景。

Typst 本身的语法也比较简洁，入门成本低。这对于程序员尤其友好，因为你不再需要跳转到复杂的菜单或选项框中去修改格式，所有内容和排版都可以通过标记语法来实现。当然，真正拿它写毕业论文时，仍然需要理解模板结构、字体路径和编译入口这些工程细节。

## 能用吗 🤷🏻‍♂️

~~如果不能用就不会有此文了~~。

软院似乎对非 `docx` 格式并不友好。曾有学长为争取使用 <span class="latex">L<span class="a">A</span>T<span class="e">E</span>X</span>，从行政老师找到院长，最终被告知支持新格式涉及大量后台工作（如查重系统适配），此事不了了之。这种先例让人对 Typst 的可行性本能地保持怀疑。

去年软院通知中，也指出要用 WORD 格式，原因则为知网和论无忧推荐。我倾向将其理解为“原则上不行，实际上可以”

<side-note>《关于2021级本科生毕业设计（论文）答辩工作的通知》要求："请在指导教师指导下，撰写毕业论文（参照《本科毕业设计（论文）工作手册，二〇二四年十月》），论文普查评分标准见《毕业设计检查表》（附件 4）。<font style="color: var(--red); font-weight: bolder;">特别说明：论文要用==WORD==格式（注：知网和论无忧推荐），论文正文字数至少 2 万字以上，论文摘要 300-500 字，参考文献至少 15 篇以上，翻译外文文献中文字数至少 1500 字以上。</font>"</side-note>

今年依旧论无忧+知网。论无忧在[功能介绍页面中明确说明支持 PDF](https://www.lun51.com/homepage/index.php?m=home&c=Lists&a=index&tid=10#:~:text=%E6%94%AF%E6%8C%81doc%E5%92%8Cdocx%E3%80%81zip%E3%80%81wps%E5%92%8Cpdf%E6%A0%BC%E5%BC%8F%EF%BC%8C%20%E6%94%AF%E6%8C%81%E5%8A%A0%E5%AF%86%E6%A3%80%E6%B5%8B)；知网查重也支持 PDF，只是更推荐 `docx`。

尽管如此，提交 `docx` 依然是最稳妥的选择。如果决定尝试 Typst，*Use at your own risk.*

## 怎么用 📝

### 下载

以 macOS 为例，通过 Homebrew 安装 Typst：

```sh
# 安装 typst，用于将 .typ 文件编译为 .pdf
brew install typst
```

安装完成后，下载示例项目并编译。这里使用的是 [qujihan/uestc-typst-thesis-example](https://github.com/qujihan/uestc-typst-thesis-example)，其中通过 submodule 引入了 [uestc-typst/thesis-template](https://github.com/uestc-typst/thesis-template)：

```sh
git clone https://github.com/qujihan/uestc-typst-thesis-example.git thesis
cd thesis
git submodule update --init --recursive
make build
```

这会生成一个名为 `学位论文写作指南及例子.pdf` 的文件。如文件名所示，你可以通过这份 PDF 快速入门 Typst 的论文写作规范。

### 语法概要

#### Headings

Typst 的正文语法接近 Markdown，但它同时是一门排版语言。使用 UESTC 模板时，最好遵循模板已经封装好的写法，让章节、图表编号、交叉引用和参考文献都交给模板处理。

标题使用等号表示层级：

```typst
= 第一章 绪论

== 研究背景

=== Web 应用的发展

==== 单页应用
```

在这个模板中，一级标题会被渲染为“第一章、第二章……”这类章节标题；二级及以下标题会自动生成类似 `1.1`、`1.1.1` 的编号。无需手动编号。

#### List

列表和 Markdown 很像。无序列表使用 `-`，有序列表使用 `+`：

```typst
- 支持会员预约
- 支持订单结算
- 支持经营分析

+ 完成需求分析
+ 完成系统设计
+ 完成测试验证
```

#### Bold & Cold

如果需要在正文中强调关键词，可以使用 `*加粗内容*`；行内代码或字段名可以使用反引号，例如 \`UserID\`、\`Status\`。

#### Figures

图片建议使用模板提供的 `picture-figure`，这样图题、编号和图目录都能自动处理：

```typst
#picture-figure(
  "系统总体架构图",
  image("pic/系统总体架构图.png", width: 80%),
)<pic-system-arch>
```

其中 `<pic-system-arch>` 是标签。正文中可以用 `@pic-system-arch` 引用它：

```typst
系统详细架构如@pic-system-arch 所示。
```

表格建议使用 `table-figure` 包一层 Typst 的 `table`。这样表题会出现在表格上方，并按“表 2-1”这类格式自动编号：

```typst
#table-figure(
  "用户角色说明",
  table(
    columns: (1fr, 2fr),
    table.header([角色], [说明]),
    [店长], [负责门店经营管理与数据分析],
    [工作人员], [负责预约、结算和日常操作],
    [会员], [通过移动端完成预约与账户管理],
  ),
)<tbl-user-roles>
```

引用表格同样使用标签：

```typst
系统用户角色见@tbl-user-roles。
```

#### Bibliography

参考文献使用 BibTeX。模板通常在 `main.typ` 中配置参考文献文件：

<side-note>BibTeX 是一种管理参考文献的格式，常和 LaTeX 一起使用。它把文献信息单独写在 .bib 文件里，然后在正文中通过引用键引用，最后自动生成参考文献列表</side-note>

```typst
info-keys.参考文献: "src/bib/参考文献1.bib",
```

BibTeX 条目可以写在 `src/bib/参考文献1.bib` 中，例如：

```bibtex
// [!code word:garrett2005ajax]
@online{garrett2005ajax,
  author = {Garrett, Jesse James},
  title  = {Ajax: A New Approach to Web Applications},
  year   = {2005},
  url    = {https://designftw.mit.edu/lectures/apis/ajax_adaptive_path.pdf},
  note   = {访问日期: 2026-04-18}
}
```

BibTeX 的类型可以根据资料来源选择，例如期刊论文常用 `@article`，会议论文常用 `@inproceedings`，学位论文常用 `@phdthesis`，网页资料常用 `@online` 或 `@misc`。不过在引用时通常无需操心，Google Scholar 等论文平台多会提供可供复制的 BibTex 条目

在正文里通过 `@garrett2005ajax` 即可引用该文献。在编译产物中 `@garrett2005ajax` 会被替换为文献的编码。假如该文献是正文中的第 x 篇文献，那么 `@garrett2005ajax` 就会被替换为 $^{[x]}$

```typst
// [!code word:@garrett2005ajax]
Garrett 提出的 Ajax 思想推动了 Web 交互模型的变化@garrett2005ajax。
```

### Use with VS Code

首先在 VS Code 中搜索并安装 `myriad-dreamin.tinymist` 插件，以获得实时预览支持。

#### 可能遇到的问题

但在实际使用中，当你编辑 `/src/chapter1.typ` 时，Tinymist LSP 可能会报错：`label <garrett2005ajax> does not exist in the document`。

原因是 Tinymist LSP 默认将当前打开的单文件视为根文档进行编译。而参考文献（bibliography）的导入操作实际上是在 `main.typ` 中完成的，`chapter1.typ` 只是被引入的子文件。

因此，我们需要让 Tinymist 始终以 `main.typ` 作为编译入口。有两种解决方案：

<x-tabs>

<x-tab title="临时方案" active>

1. 在 VS Code 中打开 `main.typ`
2. 打开命令面板 <kbd>⌘ + ⇧ + P</kbd>，执行 `Tinymist: Pin the Main File to the Current`
3. 完成

之后切换到 `chapter1.typ` 等任何子章节时，LSP 都会按照 `main.typ` 的整体上下文进行分析。如需取消固定，再次执行 `Tinymist: Unpin the Main File` 即可。

</x-tab>

<x-tab title="进阶方案">

1. 安装 tinymist 命令行工具：`{sh} brew install tinymist`
2. 编译项目，生成 `.lock` 文件：`{sh} tinymist compile --save-lock main.typ --font-path ./uestc-thesis-template/fonts --root .`
3. 在 VS Code 的 `settings.json` 中添加：`{json} "tinymist.projectResolution": "lockDatabase"` [^1]
4. 完成

这个方案的好处是能让 Tinymist 根据编译历史自动识别入口文件；代价是 `lockDatabase` 仍是实验性功能，`tinymist.lock` 的格式也可能变化。如果只是临时写论文，手动 Pin `main.typ` 反而更稳。

</x-tab>

</x-tabs>

#### 优化编辑体验的 Tips

使用 VS Code Snippets，参见[[vscode_snippets|该文章]]。下面是我常用的一组 Typst Snippet：

```json .vscode/typst.code-snippets
{
  "Typst Heading 1": {
    "prefix": "h1",
    "body": [
      "= ${1:Heading 1}",
      "$0"
    ],
    "description": "Insert a Typst level 1 heading."
  },
  "Typst Heading 2": {
    "prefix": "h2",
    "body": [
      "== ${1:Heading 2}",
      "$0"
    ],
    "description": "Insert a Typst level 2 heading."
  },
  "Typst Heading 3": {
    "prefix": "h3",
    "body": [
      "=== ${1:Heading 3}",
      "$0"
    ],
    "description": "Insert a Typst level 3 heading."
  },
  "Typst Heading 4": {
    "prefix": "h4",
    "body": [
      "==== ${1:Heading 4}",
      "$0"
    ],
    "description": "Insert a Typst level 4 heading."
  }
}
```

## 万一要交 DOCX 文件呢 😈

如果最终确实需要提交 `docx` 文件，那我是没招了，可以参考 [Typst 中文社区总结的几种转换方案](https://typst.dev/guide/FAQ/convert_to_word.html)。

### Opt 1. Microsoft Word

我恰好订阅了 *Microsoft Office 365*，打算在毕业前让它再发挥一点作用。直接用 *Microsoft Word* 打开 PDF，会自动将其另存为 `docx` 格式，转换过程很顺利，但结果完全无法接受：

![Microsoft Word's pdf to docx converter](https://assets.vluv.space/pdf2docx-20260424224445306.avif)

### Opt 2. WPS

目前比较可行的方案是：在闲鱼购买一天的 WPS 超级会员。WPS 的 PDF 转 Word 效果尚可，目录和参考文献都能保留。

![PDF to Word in WPS](https://assets.vluv.space/Clipboard-bc8ed41b418807e9df1f33ccaad17e0457ed8023df55698a6d8c9352764d1957.avif)

但仍有几个问题需要注意：

- 文字通过 OCR 识别，可能存在错字。例如个人报告里的“范式”被误识别为“范怯”
- 英文字体可以正确映射为 *Times New Roman*，但中文字体在该用宋体的地方被替换为了苹方 SC。原因大致确认了，当 WPS 在当前设备中找不到原始的“宋体”（SimSong）文件时，为了保证文字正常显示，它会自动调用系统的默认字体进行替换。

![WPS Convert to docx](https://assets.vluv.space/wps_pdf_2_word.avif)

中文字体的解决方案并不麻烦，把 `./uestc-thesis-template/fonts/SimHei.ttf` 等字体安装到系统即可。中文基本可以正确应用到SimSong, SimHei etc.

无论使用哪种转换方案，最后都要重新检查一遍这些位置：

- 目录层级和页码
- 页眉、页脚和页码格式
- 图、表、公式编号
- 参考文献编号和格式
- 中文字体、英文字体和字号
- OCR 误识别造成的错字

所以 PDF 转 DOCX 更像是兜底方案，而不是完整工作流。它能解决“必须上传 DOCX”的格式问题，但不能保证转换后的文档仍然满足论文模板的所有细节要求。

[^1]: [Project Model - Tinymist Docs](https://myriad-dreamin.github.io/tinymist/feature/project.html?utm_source=chatgpt.com#label-A%20Sample%20Usage%20of%20lockDatabase)