Polish tech-report template layout, typography, and usage guide.
Refine TOC and cover styling, add numbered headings and gray body text, unify #f6f7f8 surfaces, and replace sample content with a Markdown usage manual. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
d83e6a99a9
commit
b8b2f5fe14
@ -1,89 +1,197 @@
|
|||||||
---
|
---
|
||||||
title: 铝土矿智能分选技术报告
|
title: "GreLin 技术报告\n模板使用说明"
|
||||||
company: 西安高岭绿能科技有限公司
|
company: 西安高岭绿能科技有限公司
|
||||||
date: 2026-06-22
|
date: 2026-06-22
|
||||||
version: v2.0
|
version: v2.0
|
||||||
summary: |
|
summary: |
|
||||||
本项目拟在目标矿山建设智能矿石分选产线,以高光谱感知、深度学习推理与喷阀执行闭环为核心,实现铝土矿预选抛废与品位提升。经现场调研与算法验证,单线设计处理量 25 t/h,精矿 A/S 可达 4.0+,具备工程化落地条件。
|
本手册面向首次使用 GreLin 技术报告模板的同事,说明如何编辑 Markdown 正文、配置封面元数据、预览排版效果并导出 PDF。按章节操作即可完成一份符合 GreLin 版式规范的技术报告。
|
||||||
---
|
---
|
||||||
|
|
||||||
# 项目概述
|
# 快速开始
|
||||||
|
|
||||||
本项目面向铝土矿预选场景,建设「感知—推理—执行—运维」一体化的智能分选系统,将算法能力转化为可部署、可运维的工业产品,降低后续磨选成本并提升资源利用率。
|
技术报告的主编辑入口是 `tech-report/content/report.md`。你**几乎不需要修改 Typst 代码**,只需在该 Markdown 文件中撰写正文,并维护文件开头的 YAML 元数据。
|
||||||
|
|
||||||
> 引用块示例:政策与市场需求推动预选抛废技术应用,本段为 blockquote 样式预览。
|
推荐工作流如下:
|
||||||
|
|
||||||
**常用 Markdown 语法预览:**
|
1. 用 VS Code 或 Cursor 打开仓库,编辑 `content/report.md`。
|
||||||
|
2. 打开 `report.typ`,使用 Tinymist 扩展的 **Typst Preview** 实时预览。
|
||||||
|
3. 确认无误后,执行 **Typst Export PDF** 或使用命令行导出。
|
||||||
|
|
||||||
- **加粗**:单线处理量 `25 t/h`
|
在项目根目录执行:
|
||||||
- *斜体*:用于强调术语
|
|
||||||
- ~~删除线~~:已废弃方案
|
```bash
|
||||||
- <u>下划线</u>:关键指标标注
|
typst compile --root . tech-report/report.typ tech-report/sample.pdf
|
||||||
- Emoji:产线状态 🐱 正常 / ⚠️ 告警
|
```
|
||||||
- 行内代码:`ONNX Runtime`、`Ratatui`
|
|
||||||
|
> 提示:封面、目录、页码与正文样式已由模板封装;日常写作只需关注 `report.md` 与 `content/assets/` 中的图片资源。
|
||||||
|
|
||||||
|
# 报告元数据
|
||||||
|
|
||||||
|
元数据写在 `report.md` 最上方的 YAML 区块(两行 `---` 之间)。编译时会自动填充封面与文档属性。
|
||||||
|
|
||||||
|
常用字段如下:
|
||||||
|
|
||||||
|
| 字段 | 说明 | 示例 |
|
||||||
|
| ---- | ---- | ---- |
|
||||||
|
| `title` | 报告标题(封面与页眉) | `某某项目技术报告` |
|
||||||
|
| `company` | 编制单位 | `西安高岭绿能科技有限公司` |
|
||||||
|
| `date` | 日期,格式 `YYYY-MM-DD` | `2026-06-22` |
|
||||||
|
| `version` | 版本号 | `v1.0` |
|
||||||
|
| `summary` | 摘要正文(不含「摘要」标题,目录中也不列出) | 多行文本 |
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
title: 智能矿石分选系统技术报告
|
||||||
|
company: 西安高岭绿能科技有限公司
|
||||||
|
date: 2026-06-22
|
||||||
|
version: v1.0
|
||||||
|
summary: |
|
||||||
|
此处填写摘要段落……
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
若某字段缺省,可在 `data/config.typ` 中查看并修改默认值。
|
||||||
|
|
||||||
|
## 封面标题换行
|
||||||
|
|
||||||
|
封面主标题支持**手动指定换行**,避免长标题挤在一行显得杂乱。在 YAML 中用多行写法即可:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
title: |
|
||||||
|
GreLin 技术报告模板
|
||||||
|
使用说明
|
||||||
|
```
|
||||||
|
|
||||||
|
第一行显示为较小字号,第二行显示为更大字号(与「智能矿石分选」类报告一致)。也可在单行标题里写 `\n`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
title: "智能矿石分选\n技术报告"
|
||||||
|
```
|
||||||
|
|
||||||
|
若未手动换行,标题中含「智能」时会自动在「智能」后断开(兼容旧写法)。
|
||||||
|
|
||||||
|
# 撰写正文
|
||||||
|
|
||||||
|
## 标题层级
|
||||||
|
|
||||||
|
正文使用 Markdown 标题组织章节,模板会自动编号并套用 GreLin 样式:
|
||||||
|
|
||||||
|
- `# 一级标题` → 显示为 **1**、**2**……,整行蓝色
|
||||||
|
- `## 二级标题` → **1.1**、**1.2**……,编号蓝色、标题黑色
|
||||||
|
- `### 三级标题` → **1.1.1** 形式
|
||||||
|
- `#### 四级标题` → **1.1.1.1** 形式
|
||||||
|
|
||||||
|
标题与后续正文之间会自动换行,无需手动插入空行。
|
||||||
|
|
||||||
|
## 摘要与目录
|
||||||
|
|
||||||
|
- **摘要**:写在 YAML 的 `summary` 字段;正文区不再重复「摘要」标题,且与第一章可在同一页连续排版。
|
||||||
|
- **目录**:由模板自动生成,仅列出正文章节;摘要与「术语与缩写」不会出现在目录中。
|
||||||
|
- **术语与缩写**:在 `data/glossary.typ` 维护,报告末尾自动输出,同样不进目录。
|
||||||
|
|
||||||
|
# Markdown 语法
|
||||||
|
|
||||||
|
普通段落默认为灰色正文;需要强调时,可使用下列写法。
|
||||||
|
|
||||||
|
## 强调与高亮
|
||||||
|
|
||||||
|
- **加粗**:`**重点内容**`,仅加粗,不改变颜色
|
||||||
|
- *斜体*:`*补充说明*`,仅斜体,不改变颜色
|
||||||
|
- **高亮**:`<mark>关键指标</mark>`,浅蓝底突出显示
|
||||||
|
- <u>下划线</u>:`<u>术语或指标</u>`,蓝色下划线
|
||||||
|
- ~~删除线~~:`~~已废弃方案~~`
|
||||||
|
- 行内代码:`` `25 t/h` ``,浅灰底、等宽字体
|
||||||
|
|
||||||
|
示例:单线设计处理量 <mark>25 t/h</mark>,精矿 A/S 可达 **4.0+**。
|
||||||
|
|
||||||
|
## 链接
|
||||||
|
|
||||||
|
Markdown 链接会自动渲染为**蓝色并带下划线**:
|
||||||
|
|
||||||
|
- 带显示文字:`[GreLin 文档](https://typst.app/docs/)`
|
||||||
|
- 直接写 URL:`<https://typst.app/docs/>` 或 `https://typst.app/docs/`
|
||||||
|
|
||||||
|
示例:编译说明见 [Typst 官方文档](https://typst.app/docs/),也可访问 <https://typst.app/docs/>。
|
||||||
|
|
||||||
|
## 列表、引用与表格
|
||||||
|
|
||||||
|
无序列表:
|
||||||
|
|
||||||
|
- 条目一
|
||||||
|
- 条目二
|
||||||
|
|
||||||
|
有序列表:
|
||||||
|
|
||||||
|
1. 第一步:准备素材与数据
|
||||||
|
2. 第二步:撰写各章节
|
||||||
|
3. 第三步:预览并导出 PDF
|
||||||
|
|
||||||
|
引用块:
|
||||||
|
|
||||||
|
> 政策与市场需求推动预选抛废技术应用。引用块适合摘录标准、政策原文或补充说明。
|
||||||
|
|
||||||
|
表格示例:
|
||||||
|
|
||||||
|
| 指标 | 设计值 | 备注 |
|
||||||
|
| ---- | ------ | ---- |
|
||||||
|
| 单线处理量 | 25 t/h | 可调整 |
|
||||||
|
| 精矿 A/S | ≥ 4.0 | 实验室验证 |
|
||||||
|
|
||||||
|
## 图片与代码
|
||||||
|
|
||||||
|
图片放在 `content/assets/`,在 Markdown 中相对引用:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
代码块支持语法高亮(由 codly 渲染):
|
||||||
|
|
||||||
```python
|
```python
|
||||||
# 推理回调示例
|
# 示例:处理产线数据流
|
||||||
for sample in belt_stream:
|
for sample in belt_stream:
|
||||||
grade = model.infer(sample)
|
grade = model.infer(sample)
|
||||||
valve.fire(grade)
|
valve.fire(grade)
|
||||||
```
|
```
|
||||||
|
|
||||||
## 项目概述2
|
# 高级功能
|
||||||
|
|
||||||
建设内容包括:产线感知与推理控制软件、运营后台、运维工具及现场联调交付。
|
## 术语与缩写
|
||||||
|
|
||||||
# 建设必要性与市场分析
|
在正文中引用术语表条目,使用 raw-typst 嵌入:
|
||||||
|
|
||||||
铝土矿原料品位波动大,传统全量入磨能耗高、尾矿处置压力大。政策层面,绿色矿山与节能降碳要求推动预选抛废技术应用。目标客户在降本增效与环保合规方面需求明确,智能分选在预选环节具备可复制推广价值。
|
- 首次出现:<!--raw-typst #gls-long("hsi") -->
|
||||||
|
- 再次出现:<!--raw-typst #gls-short("onnx") -->
|
||||||
|
|
||||||
# 技术方案
|
术语定义集中在 `data/glossary.typ`,报告末尾会自动生成「术语与缩写」一节。
|
||||||
|
|
||||||
系统采用 <!--raw-typst #gls-long("hsi") --> 与 <!--raw-typst #gls-short("onnx") --> 推理引擎,构建边缘推理与喷阀执行闭环架构。
|
## 插入 Typst 组件
|
||||||
|
|
||||||
|
复杂图表或自定义组件可在 Markdown 中插入 Typst 代码:
|
||||||
|
|
||||||
<!--raw-typst #ore-sorting-flow()-->
|
<!--raw-typst #ore-sorting-flow()-->
|
||||||
|
|
||||||

|
如需新增组件,在 `data/` 下编写 Typst 函数,并在 `report.typ` 的 `extra-scope` 中注册后,即可用 `<!--raw-typst #函数名()-->` 调用。
|
||||||
|
|
||||||
核心技术路线:
|
# 版式说明
|
||||||
|
|
||||||
- 高光谱采集与样本标准化处理
|
| 页面 | 边距 | 说明 |
|
||||||
- ONNX 推理服务与产线实时回调
|
| ---- | ---- | ---- |
|
||||||
- Rust 运维控制台与产线状态监控
|
| 封面 | 自定义 | 左侧蓝色色块贴边,见 `data/cover.typ` |
|
||||||
|
| 目录 | 2.5 cm | 较宽边距,便于大号章节编号排版 |
|
||||||
|
| 正文 | 2 cm | 摘要及正文内容使用较窄边距 |
|
||||||
|
|
||||||
## 验证指标(实验室 / 现场)
|
正文无页眉;页码从正文第一章起算,格式为 `当前页 / 总页数`,位于页脚右侧。
|
||||||
|
|
||||||
| 指标 | 设计值 | 验证情况 |
|
# 常见问题
|
||||||
| ---- | ------ | -------- |
|
|
||||||
| 单线处理量 | 25 t/h | 已验证 |
|
|
||||||
| 精矿 <!--raw-typst #gls-short("as-ratio") --> | ≥ 4.0 | 4.0+ |
|
|
||||||
| 尾矿 A/S | ≤ 1.7 | 1.7- |
|
|
||||||
| 回收率 | ≥ 30% | 30%+ |
|
|
||||||
|
|
||||||
# 实施计划
|
**Q:修改 Markdown 后预览没有更新?**
|
||||||
|
A:保存 `report.md` 后,Typst Preview 通常会自动刷新;若无反应,可关闭预览后重新打开 `report.typ`。
|
||||||
|
|
||||||
1. **研发验证**(1–2 月):算法迭代、软件模块开发与台架测试。
|
**Q:图片找不到?**
|
||||||
2. **试点部署**(2–3 月):单线现场安装、联调与试运行。
|
A:确认路径相对于 `content/report.md`,且文件位于 `content/assets/` 目录下。
|
||||||
3. **规模化推广**(持续):复制部署、运维体系与客户培训。
|
|
||||||
|
|
||||||
# 投资估算与资金用途
|
**Q:想改主题色或字号?**
|
||||||
|
A:编辑 `data/theme.typ`;品牌色也可在仓库根目录 `brand/colors.typ` 统一调整。
|
||||||
|
|
||||||
投资主要用于光谱传感与执行机构硬件、软件开发与现场实施、人员与运维体系建设。具体金额结合矿山规模与产线配置在商务阶段细化。
|
完成以上步骤后,你即可基于本模板快速产出 GreLin 风格的技术报告。祝写作顺利。
|
||||||
|
|
||||||
# 效益分析
|
|
||||||
|
|
||||||
- **经济效益**:减少入磨量,降低能耗与药剂成本;提升精矿品位与回收率。
|
|
||||||
- **环保效益**:减少尾矿产生量,降低固废处置压力。
|
|
||||||
- **社会效益**:支撑绿色矿山建设,提升企业技术形象。
|
|
||||||
|
|
||||||
# 风险分析与对策
|
|
||||||
|
|
||||||
| 风险 | 对策 |
|
|
||||||
| ---- | ---- |
|
|
||||||
| 原料波动影响模型稳定性 | 持续采样标注与模型迭代;异常降级策略 |
|
|
||||||
| 现场交付周期 | 标准化模块与运维工具;阶段里程碑管控 |
|
|
||||||
| 客户接受度 | 试点数据透明展示;可量化的效益测算 |
|
|
||||||
|
|
||||||
# 结论
|
|
||||||
|
|
||||||
综合技术验证、市场需求与实施条件,本项目具备可行性。建议推进试点产线建设,以现场数据支撑后续规模化复制。
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
default-color: color-body,
|
default-color: color-body,
|
||||||
lang-stroke: (_) => none,
|
lang-stroke: (_) => none,
|
||||||
lang-fill: (_) => code-block-fill,
|
lang-fill: (_) => code-block-fill,
|
||||||
lang-radius: 0pt,
|
lang-radius: code-block-radius,
|
||||||
)
|
)
|
||||||
|
|
||||||
/// 与 codly 配合的语法高亮色(须在 codly-init 之后注册)
|
/// 与 codly 配合的语法高亮色(须在 codly-init 之后注册)
|
||||||
|
|||||||
@ -11,17 +11,25 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#let cover-title-lines(title) = {
|
#let cover-title-lines(title) = {
|
||||||
|
let trimmed = title.trim()
|
||||||
|
if trimmed.contains("\n") {
|
||||||
|
let parts = trimmed.split("\n").filter(p => p.trim().len() > 0)
|
||||||
|
if parts.len() >= 2 {
|
||||||
|
return (parts.at(0).trim(), parts.slice(1).join(" ").trim())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let marker = "智能"
|
let marker = "智能"
|
||||||
let m = title.match(regex(marker))
|
let m = trimmed.match(regex(marker))
|
||||||
if m == none {
|
if m == none {
|
||||||
(title, none)
|
(trimmed, none)
|
||||||
} else {
|
} else {
|
||||||
let end = m.end
|
let end = m.end
|
||||||
let line-2 = title.slice(end)
|
let line-2 = trimmed.slice(end)
|
||||||
if line-2.len() > 0 {
|
if line-2.len() > 0 {
|
||||||
(title.slice(0, end), line-2)
|
(trimmed.slice(0, end), line-2)
|
||||||
} else {
|
} else {
|
||||||
(title, none)
|
(trimmed, none)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#import "@preview/cmarker:0.1.8": render-with-metadata
|
#import "@preview/cmarker:0.1.8": render-with-metadata
|
||||||
#import "config.typ": *
|
#import "config.typ": *
|
||||||
#import "theme.typ": *
|
#import "theme.typ": *
|
||||||
#import "styling.typ": underline-accent
|
#import "styling.typ": underline-accent, text-highlight
|
||||||
|
|
||||||
#let source-dir(path) = {
|
#let source-dir(path) = {
|
||||||
let parts = path.split("/")
|
let parts = path.split("/")
|
||||||
@ -57,6 +57,7 @@
|
|||||||
smart-punctuation: true,
|
smart-punctuation: true,
|
||||||
html: (
|
html: (
|
||||||
u: (_, body) => underline-accent(body),
|
u: (_, body) => underline-accent(body),
|
||||||
|
mark: (_, body) => text-highlight(body),
|
||||||
),
|
),
|
||||||
scope: (
|
scope: (
|
||||||
image: (source, alt: none) => resolve-image(source-path, source, alt: alt),
|
image: (source, alt: none) => resolve-image(source-path, source, alt: alt),
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#let transit-red = rgb("#c53a2f")
|
#let transit-red = rgb("#c53a2f")
|
||||||
|
#import "theme.typ": color-quote, code-block-radius, code-inline-radius, quote-bar-stroke, quote-bar-color, color-body-text, color-block-bg, tw
|
||||||
#let metro-blue = rgb("#005f9e")
|
#let metro-blue = rgb("#005f9e")
|
||||||
#let deep-teal = rgb("#0f766e")
|
#let deep-teal = rgb("#0f766e")
|
||||||
#let burnt-orange = rgb("#c96b2c")
|
#let burnt-orange = rgb("#c96b2c")
|
||||||
@ -24,6 +25,7 @@
|
|||||||
date-format: "[day] [month repr:long] [year]",
|
date-format: "[day] [month repr:long] [year]",
|
||||||
cover-page: false,
|
cover-page: false,
|
||||||
inline-title: true,
|
inline-title: true,
|
||||||
|
show-header: false,
|
||||||
// -- Page margins (override metropole defaults) --
|
// -- Page margins (override metropole defaults) --
|
||||||
margin-x: none,
|
margin-x: none,
|
||||||
margin-y: none,
|
margin-y: none,
|
||||||
@ -37,6 +39,7 @@
|
|||||||
// -- Colors --
|
// -- Colors --
|
||||||
background-color: rgb("#ffffff"),
|
background-color: rgb("#ffffff"),
|
||||||
foreground-color: rgb("000000"),
|
foreground-color: rgb("000000"),
|
||||||
|
body-text-color: none,
|
||||||
accent-color: transit-red,
|
accent-color: transit-red,
|
||||||
// -- Body --
|
// -- Body --
|
||||||
body,
|
body,
|
||||||
@ -61,11 +64,6 @@
|
|||||||
(background-color, 1),
|
(background-color, 1),
|
||||||
space: oklab,
|
space: oklab,
|
||||||
)
|
)
|
||||||
let block-bg-color = color.mix(
|
|
||||||
(background-color, 20),
|
|
||||||
(foreground-color, 1),
|
|
||||||
space: oklab,
|
|
||||||
)
|
|
||||||
let link-color = color.mix(
|
let link-color = color.mix(
|
||||||
(accent-color, 3),
|
(accent-color, 3),
|
||||||
(foreground-color, 1),
|
(foreground-color, 1),
|
||||||
@ -87,10 +85,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ── Configure text --
|
// ── Configure text --
|
||||||
|
let body-fill = if body-text-color != none { body-text-color } else { foreground-color }
|
||||||
set text(
|
set text(
|
||||||
font: body-font,
|
font: body-font,
|
||||||
size: font-size,
|
size: font-size,
|
||||||
fill: foreground-color,
|
fill: body-fill,
|
||||||
ligatures: true,
|
ligatures: true,
|
||||||
discretionary-ligatures: true,
|
discretionary-ligatures: true,
|
||||||
lang: language,
|
lang: language,
|
||||||
@ -123,7 +122,8 @@
|
|||||||
top: margin-vertical,
|
top: margin-vertical,
|
||||||
bottom: margin-vertical,
|
bottom: margin-vertical,
|
||||||
),
|
),
|
||||||
header: context {
|
header: if show-header {
|
||||||
|
context {
|
||||||
if counter(page).get().first() > 1 {
|
if counter(page).get().first() > 1 {
|
||||||
v(header-gap)
|
v(header-gap)
|
||||||
grid(
|
grid(
|
||||||
@ -145,8 +145,11 @@
|
|||||||
)
|
)
|
||||||
v(line-height / 2)
|
v(line-height / 2)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
none
|
||||||
},
|
},
|
||||||
header-ascent: line-height / 2,
|
header-ascent: if show-header { line-height / 2 } else { 0pt },
|
||||||
footer: context {
|
footer: context {
|
||||||
v(line-height / 2)
|
v(line-height / 2)
|
||||||
if page-numbering-started.at(here()) {
|
if page-numbering-started.at(here()) {
|
||||||
@ -162,38 +165,46 @@
|
|||||||
)
|
)
|
||||||
|
|
||||||
// ── Configure headings --
|
// ── Configure headings --
|
||||||
show heading.where(level: 1): it => context {
|
let report-heading(it, size, above, below, title-fill: foreground-color) = block(
|
||||||
v(line-height * 2, weak: true)
|
width: 100%,
|
||||||
|
breakable: false,
|
||||||
|
above: above,
|
||||||
|
below: below,
|
||||||
|
)[
|
||||||
|
#context {
|
||||||
|
if it.numbering != none {
|
||||||
|
let number = counter(heading).display(it.numbering)
|
||||||
|
text(font: heading-font, size: size, weight: "bold")[
|
||||||
|
#text(fill: accent-color)[#number]
|
||||||
|
#h(0.35em)
|
||||||
|
#text(fill: title-fill)[#it.body]
|
||||||
|
]
|
||||||
|
} else {
|
||||||
text(
|
text(
|
||||||
font: heading-font,
|
font: heading-font,
|
||||||
size: heading-size,
|
size: size,
|
||||||
weight: "bold",
|
weight: "bold",
|
||||||
fill: accent-color,
|
fill: title-fill,
|
||||||
it.body,
|
it.body,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
show heading.where(level: 2): it => context {
|
show heading.where(level: 1): it => {
|
||||||
v(line-height * 2, weak: true)
|
report-heading(it, heading-size, line-height * 2, line-height, title-fill: accent-color)
|
||||||
text(
|
}
|
||||||
font: heading-font,
|
|
||||||
size: lead-size,
|
show heading.where(level: 2): it => {
|
||||||
weight: "bold",
|
report-heading(it, lead-size, line-height * 2, line-height * 0.85)
|
||||||
fill: foreground-color,
|
|
||||||
it.body,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
show heading.where(level: 3): it => {
|
show heading.where(level: 3): it => {
|
||||||
v(line-height, weak: true)
|
report-heading(it, font-size, line-height, line-height * 0.75)
|
||||||
text(
|
}
|
||||||
font: heading-font,
|
|
||||||
size: font-size,
|
show heading.where(level: 4): it => {
|
||||||
weight: "bold",
|
report-heading(it, caption-size, line-height * 0.85, line-height * 0.65)
|
||||||
fill: foreground-color,
|
|
||||||
it.body,
|
|
||||||
)
|
|
||||||
v(line-height / 2, weak: true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Configure lists --
|
// ── Configure lists --
|
||||||
@ -245,17 +256,14 @@
|
|||||||
|
|
||||||
// -- Configure block quotes --
|
// -- Configure block quotes --
|
||||||
show quote.where(block: true): it => {
|
show quote.where(block: true): it => {
|
||||||
v(line-height, weak: true)
|
v(line-height * 0.75, weak: true)
|
||||||
block(width: 100%)[
|
block(width: 100%)[
|
||||||
#place(left + top, dy: -line-height / 2, text(
|
#block(
|
||||||
font: heading-font,
|
width: 100%,
|
||||||
size: display-size * 2,
|
inset: (left: tw(3.5)),
|
||||||
fill: block-bg-color,
|
stroke: (left: quote-bar-stroke + quote-bar-color),
|
||||||
weight: "bold",
|
)[
|
||||||
["],
|
#text(font: body-font, fill: color-body-text, it.body)
|
||||||
))
|
|
||||||
#pad(left: lead-size)[
|
|
||||||
#text(font: body-font, style: "italic", it.body)
|
|
||||||
#if it.attribution != none {
|
#if it.attribution != none {
|
||||||
v(line-height / 2, weak: true)
|
v(line-height / 2, weak: true)
|
||||||
align(right, text(
|
align(right, text(
|
||||||
@ -267,17 +275,27 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
v(line-height, weak: true)
|
v(line-height * 0.75, weak: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- Configure tables --
|
// -- Configure tables --
|
||||||
|
show table: it => {
|
||||||
|
if it.has("label") and it.label == <table-full-width> {
|
||||||
|
it
|
||||||
|
} else {
|
||||||
|
[#table(
|
||||||
|
columns: (1fr,) * it.columns.len(),
|
||||||
|
..it.children,
|
||||||
|
)#label("table-full-width")]
|
||||||
|
}
|
||||||
|
}
|
||||||
set table(
|
set table(
|
||||||
stroke: none,
|
stroke: none,
|
||||||
inset: (x: line-height / 2, y: line-height / 2),
|
inset: (x: line-height / 2, y: line-height / 2),
|
||||||
fill: (x, y) => if y == 0 {
|
fill: (x, y) => if y == 0 {
|
||||||
accent-color
|
accent-color
|
||||||
} else if calc.odd(y) {
|
} else if calc.even(y) {
|
||||||
block-bg-color
|
color-block-bg
|
||||||
} else {
|
} else {
|
||||||
none
|
none
|
||||||
},
|
},
|
||||||
@ -296,21 +314,24 @@
|
|||||||
show raw.where(block: true): block.with(
|
show raw.where(block: true): block.with(
|
||||||
inset: (x: line-height, y: line-height / 2),
|
inset: (x: line-height, y: line-height / 2),
|
||||||
width: 100%,
|
width: 100%,
|
||||||
fill: block-bg-color,
|
fill: color-block-bg,
|
||||||
|
radius: code-block-radius,
|
||||||
)
|
)
|
||||||
show raw.where(block: true): set par(justify: false)
|
show raw.where(block: true): set par(justify: false)
|
||||||
show raw.where(block: false): box.with(
|
show raw.where(block: false): box.with(
|
||||||
inset: (x: 3pt, y: 0pt),
|
inset: (x: 3pt, y: 0pt),
|
||||||
outset: (y: 3pt),
|
outset: (y: 3pt),
|
||||||
fill: block-bg-color,
|
fill: color-block-bg,
|
||||||
|
radius: code-inline-radius,
|
||||||
)
|
)
|
||||||
|
show raw.where(block: false): set text(fill: foreground-color)
|
||||||
|
|
||||||
// ── Configure links --
|
// ── Configure links --
|
||||||
show link: it => {
|
show link: it => {
|
||||||
if type(it.dest) != str {
|
if type(it.dest) != str {
|
||||||
it
|
it
|
||||||
} else {
|
} else {
|
||||||
text(fill: link-color, it)
|
text(fill: accent-color, underline(it.body))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,3 +6,11 @@
|
|||||||
offset: 4pt,
|
offset: 4pt,
|
||||||
evade: true,
|
evade: true,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
#let text-highlight(body) = highlight(
|
||||||
|
body,
|
||||||
|
fill: color-accent-surface,
|
||||||
|
top-edge: "ascender",
|
||||||
|
bottom-edge: "descender",
|
||||||
|
radius: tw(0.5),
|
||||||
|
)
|
||||||
|
|||||||
@ -6,15 +6,15 @@
|
|||||||
#let color-accent = color-primary
|
#let color-accent = color-primary
|
||||||
#let color-accent-surface = color-primary.lighten(88%)
|
#let color-accent-surface = color-primary.lighten(88%)
|
||||||
#let color-heading = color-ink
|
#let color-heading = color-ink
|
||||||
|
#let color-body-text = color-body
|
||||||
#let color-caption = rgb(110, 110, 110)
|
#let color-caption = rgb(110, 110, 110)
|
||||||
#let color-quote = rgb(90, 90, 90)
|
#let color-quote = rgb(90, 90, 90)
|
||||||
|
#let quote-bar-stroke = 2.5pt
|
||||||
|
#let quote-bar-color = rgb("#f6f7f8")
|
||||||
|
#let table-stroke-color = color-muted.lighten(50%)
|
||||||
#let color-code-inline = color-ink
|
#let color-code-inline = color-ink
|
||||||
#let color-page = white
|
#let color-page = white
|
||||||
#let color-block-bg = color.mix(
|
#let color-block-bg = rgb("#f6f7f8")
|
||||||
(white, 20),
|
|
||||||
(color-ink, 1),
|
|
||||||
space: oklab,
|
|
||||||
)
|
|
||||||
|
|
||||||
#let code-token-keyword = color-ink
|
#let code-token-keyword = color-ink
|
||||||
#let code-token-comment = rgb(130, 130, 130)
|
#let code-token-comment = rgb(130, 130, 130)
|
||||||
@ -45,13 +45,16 @@
|
|||||||
#let image-max-width = 100%
|
#let image-max-width = 100%
|
||||||
|
|
||||||
#let code-block-fill = color-block-bg
|
#let code-block-fill = color-block-bg
|
||||||
#let code-block-radius = 0pt
|
#let code-block-radius = tw(1.5)
|
||||||
|
#let code-inline-radius = tw(0.75)
|
||||||
#let code-inline-fill = color-block-bg
|
#let code-inline-fill = color-block-bg
|
||||||
|
|
||||||
// --- 页面边距(A4 常用 2.5 cm)---
|
// --- 页面边距 ---
|
||||||
#let page-margin-a4 = 2.5cm
|
#let page-margin-a4 = 2.5cm
|
||||||
#let page-margin-x = page-margin-a4
|
#let page-margin-x = page-margin-a4
|
||||||
#let page-margin-y = page-margin-a4
|
#let page-margin-y = page-margin-a4
|
||||||
|
#let body-margin-x = 2cm
|
||||||
|
#let body-margin-y = 2cm
|
||||||
|
|
||||||
// --- 封面页边距(色块左贴边 · 上下等距)---
|
// --- 封面页边距(色块左贴边 · 上下等距)---
|
||||||
#let cover-margin-y = tw(8)
|
#let cover-margin-y = tw(8)
|
||||||
@ -131,9 +134,9 @@
|
|||||||
#let toc-content-indent = tw(12)
|
#let toc-content-indent = tw(12)
|
||||||
#let summary-top-offset = tw(10)
|
#let summary-top-offset = tw(10)
|
||||||
#let summary-body-gap = tw(8)
|
#let summary-body-gap = tw(8)
|
||||||
#let toc-head-zh = text-4xl
|
#let toc-head-zh = text-5xl
|
||||||
#let toc-l2-color = color-muted.lighten(28%)
|
#let toc-l2-color = color-muted.lighten(28%)
|
||||||
#let toc-head-color = toc-l2-color
|
#let toc-head-color = color-primary
|
||||||
#let toc-classification-label = "C3 Confidential"
|
#let toc-classification-label = "C3 Confidential"
|
||||||
#let toc-classification-size = text-xs
|
#let toc-classification-size = text-xs
|
||||||
#let toc-classification-color = toc-l2-color
|
#let toc-classification-color = toc-l2-color
|
||||||
@ -143,7 +146,7 @@
|
|||||||
#let toc-l1-number-title-gap = tw(11)
|
#let toc-l1-number-title-gap = tw(11)
|
||||||
#let toc-l1-number-size = text-5xl
|
#let toc-l1-number-size = text-5xl
|
||||||
#let toc-l1-number-color = color-primary
|
#let toc-l1-number-color = color-primary
|
||||||
#let toc-l1-size = text-base
|
#let toc-l1-size = text-lg
|
||||||
#let toc-l2-size = text-sm
|
#let toc-l2-size = text-sm
|
||||||
#let toc-page-size = text-sm
|
#let toc-page-size = text-sm
|
||||||
#let toc-l1-color = color-primary
|
#let toc-l1-color = color-primary
|
||||||
|
|||||||
@ -59,24 +59,23 @@
|
|||||||
cover-page: false,
|
cover-page: false,
|
||||||
inline-title: false,
|
inline-title: false,
|
||||||
accent-color: color-primary,
|
accent-color: color-primary,
|
||||||
|
body-text-color: color-body-text,
|
||||||
body-font: body-font,
|
body-font: body-font,
|
||||||
heading-font: heading-font,
|
heading-font: heading-font,
|
||||||
raw-font: mono-font,
|
raw-font: mono-font,
|
||||||
font-size: size-body,
|
font-size: size-body,
|
||||||
leading-ratio: leading-ratio,
|
leading-ratio: leading-ratio,
|
||||||
margin-x: page-margin-x,
|
margin-x: body-margin-x,
|
||||||
margin-y: page-margin-y,
|
margin-y: body-margin-y,
|
||||||
)
|
)
|
||||||
|
|
||||||
#set heading(numbering: "1.1.1")
|
#set heading(numbering: "1.1.1.1")
|
||||||
#show: toc-register-chapter-counter()
|
#show: toc-register-chapter-counter()
|
||||||
|
|
||||||
#toc-page(meta)
|
#toc-page(meta)
|
||||||
|
|
||||||
#if meta.summary != "" [
|
#if meta.summary != "" [
|
||||||
#v(summary-top-offset, weak: false)
|
#v(summary-top-offset, weak: false)
|
||||||
#text(font: heading-font, size: size-h1, weight: "bold", fill: color-heading)[摘要]
|
|
||||||
#v(tw(3))
|
|
||||||
#meta.summary
|
#meta.summary
|
||||||
#v(summary-body-gap)
|
#v(summary-body-gap)
|
||||||
]
|
]
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user