Compare commits
No commits in common. "5c1039c62d58f0f03bda6bd72159ea547bf8fda0" and "769decd44514dfe9c45155890d9819ae1713b045" have entirely different histories.
5c1039c62d
...
769decd445
8
.gitignore
vendored
8
.gitignore
vendored
@ -2,15 +2,13 @@
|
|||||||
*.pdf
|
*.pdf
|
||||||
!resume-bp/sample.pdf
|
!resume-bp/sample.pdf
|
||||||
!resume-career/sample.pdf
|
!resume-career/sample.pdf
|
||||||
!tech-report/sample.pdf
|
!feasibility/sample.pdf
|
||||||
!presentation/sample.pdf
|
|
||||||
!travel-plan/sample.pdf
|
|
||||||
|
|
||||||
# 本地定制(个人内容、照片、PDF,不提交)
|
# 本地定制简历(个人内容、照片、PDF,不提交)
|
||||||
resume-bp/local/*
|
resume-bp/local/*
|
||||||
!resume-bp/local/README.md
|
!resume-bp/local/README.md
|
||||||
resume-career/local/*
|
resume-career/local/*
|
||||||
travel-plan/local/*
|
!resume-career/local/README.md
|
||||||
|
|
||||||
# IDE / 编辑器本地配置
|
# IDE / 编辑器本地配置
|
||||||
.cursor/
|
.cursor/
|
||||||
|
|||||||
@ -6,9 +6,7 @@ GreLin 内部 Typst 模板库,按文档类型分目录维护。目录结构如
|
|||||||
|--------|------|----------|
|
|--------|------|----------|
|
||||||
| [`resume-bp/`](resume-bp/) | 融资 BP 团队简历(完整版,含证件照) | `cv.typ` |
|
| [`resume-bp/`](resume-bp/) | 融资 BP 团队简历(完整版,含证件照) | `cv.typ` |
|
||||||
| [`resume-career/`](resume-career/) | 求职 / 个人主页简历(精简一页) | `cv.typ`(内容 `data/config.typ`) |
|
| [`resume-career/`](resume-career/) | 求职 / 个人主页简历(精简一页) | `cv.typ`(内容 `data/config.typ`) |
|
||||||
| [`tech-report/`](tech-report/) | 技术报告 | `report.typ`(正文编辑 `tech-report/content/report.md`) |
|
| [`feasibility/`](feasibility/) | 可行性研究报告 | `report.typ`(正文编辑 `feasibility/content/report.md`) |
|
||||||
| [`presentation/`](presentation/) | PPT 演示文稿(16:9,待完善) | `deck.typ`(内容 `data/config.typ`) |
|
|
||||||
| [`travel-plan/`](travel-plan/) | 旅行计划(参考图、链接、行程) | `trips/<名>/` · 可选 `plan.typ` |
|
|
||||||
|
|
||||||
## 环境要求
|
## 环境要求
|
||||||
|
|
||||||
@ -17,8 +15,8 @@ GreLin 内部 Typst 模板库,按文档类型分目录维护。目录结构如
|
|||||||
|
|
||||||
## 快速开始
|
## 快速开始
|
||||||
|
|
||||||
1. 用 VS Code / Cursor 打开本仓库,打开要编辑的入口文件,例如 `resume-bp/cv.typ`、`resume-career/cv.typ`、`presentation/deck.typ` 或 `tech-report/report.typ`
|
1. 用 VS Code / Cursor 打开本仓库,打开要编辑的入口文件,例如 `resume-bp/cv.typ`、`resume-career/cv.typ` 或 `feasibility/report.typ`
|
||||||
2. 技术报告正文在 `tech-report/content/report.md` 用 Markdown 编写,无需改 Typst 代码
|
2. 可行性报告正文在 `feasibility/content/report.md` 用 Markdown 编写,无需改 Typst 代码
|
||||||
3. 看效果(预览):`Ctrl+Shift+P` → 输入 `Typst Preview` → 回车;侧边会实时显示排版效果
|
3. 看效果(预览):`Ctrl+Shift+P` → 输入 `Typst Preview` → 回车;侧边会实时显示排版效果
|
||||||
4. 导出 PDF:`Ctrl+Shift+P` → 输入 `Typst Export PDF` → 回车;PDF 默认生成在同目录
|
4. 导出 PDF:`Ctrl+Shift+P` → 输入 `Typst Export PDF` → 回车;PDF 默认生成在同目录
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// GreLin 品牌色板 — 全文档统一(resume-bp / resume-career / tech-report / presentation 等均 import 此文件)
|
// GreLin 品牌色板 — 全文档统一(resume-bp / resume-career / feasibility 等均 import 此文件)
|
||||||
|
|
||||||
#let color-ink = rgb("#08090B")
|
#let color-ink = rgb("#08090B")
|
||||||
#let color-body = rgb("#2D3135")
|
#let color-body = rgb("#2D3135")
|
||||||
|
|||||||
74
feasibility/README.md
Normal file
74
feasibility/README.md
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
# Feasibility Report · 可行性研究报告模板
|
||||||
|
|
||||||
|
GreLin 可行性报告 Typst 模板,面向矿石分选项目论证与客户交付。同事用 **Markdown** 写正文,模板负责封面、页眉页脚与图表排版。
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
1. 编辑 [`content/report.md`](content/report.md)(或从 [`content/report.template.md`](content/report.template.md) 复制)
|
||||||
|
2. 用 VS Code / Cursor 打开 [`report.typ`](report.typ)
|
||||||
|
3. `Ctrl+Shift+P` → **Typst Preview** 预览,或 **Typst Export PDF** 导出
|
||||||
|
|
||||||
|
仓库根目录编译(共享 `brand/colors.typ`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
typst compile feasibility/report.typ feasibility/sample.pdf --root .
|
||||||
|
```
|
||||||
|
|
||||||
|
示例输出:[`sample.pdf`](sample.pdf)
|
||||||
|
|
||||||
|
## 工作流
|
||||||
|
|
||||||
|
| 文件 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| [`content/report.md`](content/report.md) | **主编辑入口**:YAML 元数据 + 正文 |
|
||||||
|
| [`content/assets/`](content/assets/) | 图片资源(支持 `.jpg` / `.png` / `.svg`) |
|
||||||
|
| [`data/config.typ`](data/config.typ) | 默认公司名、副标题等(YAML 未写时使用) |
|
||||||
|
| [`data/theme.typ`](data/theme.typ) | 设计 token(字号、间距、表格) |
|
||||||
|
| [`data/styling.typ`](data/styling.typ) | 标题 / 表格 / 图片 `#show` 规范 |
|
||||||
|
| [`data/layout.typ`](data/layout.typ) | 封面、摘要、页眉组件 |
|
||||||
|
| [`report.typ`](report.typ) | 编译入口(一般无需改动) |
|
||||||
|
|
||||||
|
## YAML 元数据
|
||||||
|
|
||||||
|
在 `report.md` 顶部填写:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
title: 某某矿山智能分选可行性研究
|
||||||
|
brand: GreLin
|
||||||
|
company: 西安高岭绿能科技有限公司
|
||||||
|
date: 2026-06-22
|
||||||
|
version: v1.0
|
||||||
|
summary: |
|
||||||
|
摘要正文……
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
## Markdown 写法
|
||||||
|
|
||||||
|
- 章节:`# 项目概述`(自动编号为 1. / 1.1 / 1.1.1,无需手写「一、二、三」)
|
||||||
|
- 表格:标准 GFM 表格语法
|
||||||
|
- 图片:`` 或 `assets/chart.png`,文件放在 `content/assets/`
|
||||||
|
- 行内代码:`` `ONNX Runtime` ``(灰底、小圆角、品牌色文字)
|
||||||
|
- 代码块:` ```python ` 围栏 + 语言名,由 [codly](https://typst.app/universe/package/codly) 自动语法高亮并显示语言标签
|
||||||
|
- 下划线:`<u>文字</u>`(品牌色,线下移 5pt)
|
||||||
|
- Emoji:正文可直接写 🐱 等符号(需系统字体支持)
|
||||||
|
- 列表、加粗等均支持(基于 [cmarker](https://typst.app/universe/package/cmarker))
|
||||||
|
|
||||||
|
## 依赖包
|
||||||
|
|
||||||
|
| 包 | 用途 |
|
||||||
|
|----|------|
|
||||||
|
| [cmarker](https://typst.app/universe/package/cmarker) | Markdown → Typst 正文 |
|
||||||
|
| [codly](https://typst.app/universe/package/codly) + [codly-languages](https://typst.app/universe/package/codly-languages) | 代码块高亮与语言标签 |
|
||||||
|
|
||||||
|
可选扩展:[toutu](https://typst.app/universe/package/toutu)(目录)、[hydra](https://typst.app/universe/package/hydra)(页眉章节名)、[cetz](https://typst.app/universe/package/cetz)(矢量图表)。
|
||||||
|
|
||||||
|
## 环境要求
|
||||||
|
|
||||||
|
- **Typst ≥ 0.14.0**;请使用较新版本的 Tinymist 或 Typst CLI
|
||||||
|
- 首次编译会自动下载 `cmarker`、`codly`、`codly-languages`(需网络)
|
||||||
|
|
||||||
|
## 替换外部 MD
|
||||||
|
|
||||||
|
将同事发来的 `.md` 覆盖 `content/report.md`,图片放入 `content/assets/` 并修正文内路径,重新预览即可。
|
||||||
|
Before Width: | Height: | Size: 251 KiB After Width: | Height: | Size: 251 KiB |
89
feasibility/content/report.md
Normal file
89
feasibility/content/report.md
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
---
|
||||||
|
title: 铝土矿可行性研究报告
|
||||||
|
company: 西安高岭绿能科技有限公司
|
||||||
|
date: 2026-06-22
|
||||||
|
version: v1.0
|
||||||
|
summary: |
|
||||||
|
本项目拟在目标矿山建设智能矿石分选产线,以高光谱感知、深度学习推理与喷阀执行闭环为核心,实现铝土矿预选抛废与品位提升。经现场调研与算法验证,单线设计处理量 25 t/h,精矿 A/S 可达 4.0+,具备工程化落地条件。
|
||||||
|
---
|
||||||
|
|
||||||
|
# 项目概述
|
||||||
|
|
||||||
|
本项目面向铝土矿预选场景,建设「感知—推理—执行—运维」一体化的智能分选系统,将算法能力转化为可部署、可运维的工业产品,降低后续磨选成本并提升资源利用率。
|
||||||
|
|
||||||
|
> 引用块示例:政策与市场需求推动预选抛废技术应用,本段为 blockquote 样式预览。
|
||||||
|
|
||||||
|
**常用 Markdown 语法预览:**
|
||||||
|
|
||||||
|
- **加粗**:单线处理量 `25 t/h`
|
||||||
|
- *斜体*:用于强调术语
|
||||||
|
- ~~删除线~~:已废弃方案
|
||||||
|
- <u>下划线</u>:关键指标标注
|
||||||
|
- Emoji:产线状态 🐱 正常 / ⚠️ 告警
|
||||||
|
- 行内代码:`ONNX Runtime`、`Ratatui`
|
||||||
|
|
||||||
|
```python
|
||||||
|
# 推理回调示例
|
||||||
|
for sample in belt_stream:
|
||||||
|
grade = model.infer(sample)
|
||||||
|
valve.fire(grade)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 项目概述2
|
||||||
|
|
||||||
|
建设内容包括:产线感知与推理控制软件、运营后台、运维工具及现场联调交付。
|
||||||
|
|
||||||
|
# 建设必要性与市场分析
|
||||||
|
|
||||||
|
铝土矿原料品位波动大,传统全量入磨能耗高、尾矿处置压力大。政策层面,绿色矿山与节能降碳要求推动预选抛废技术应用。目标客户在降本增效与环保合规方面需求明确,智能分选在预选环节具备可复制推广价值。
|
||||||
|
|
||||||
|
# 技术方案
|
||||||
|
|
||||||
|
系统采用 <!--raw-typst #gls-long("hsi") --> 与 <!--raw-typst #gls-short("onnx") --> 推理引擎,构建边缘推理与喷阀执行闭环架构。
|
||||||
|
|
||||||
|
<!--raw-typst #ore-sorting-flow()-->
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
核心技术路线:
|
||||||
|
|
||||||
|
- 高光谱采集与样本标准化处理
|
||||||
|
- ONNX 推理服务与产线实时回调
|
||||||
|
- Rust 运维控制台与产线状态监控
|
||||||
|
|
||||||
|
## 验证指标(实验室 / 现场)
|
||||||
|
|
||||||
|
| 指标 | 设计值 | 验证情况 |
|
||||||
|
| ---- | ------ | -------- |
|
||||||
|
| 单线处理量 | 25 t/h | 已验证 |
|
||||||
|
| 精矿 <!--raw-typst #gls-short("as-ratio") --> | ≥ 4.0 | 4.0+ |
|
||||||
|
| 尾矿 A/S | ≤ 1.7 | 1.7- |
|
||||||
|
| 回收率 | ≥ 30% | 30%+ |
|
||||||
|
|
||||||
|
# 实施计划
|
||||||
|
|
||||||
|
1. **研发验证**(1–2 月):算法迭代、软件模块开发与台架测试。
|
||||||
|
2. **试点部署**(2–3 月):单线现场安装、联调与试运行。
|
||||||
|
3. **规模化推广**(持续):复制部署、运维体系与客户培训。
|
||||||
|
|
||||||
|
# 投资估算与资金用途
|
||||||
|
|
||||||
|
投资主要用于光谱传感与执行机构硬件、软件开发与现场实施、人员与运维体系建设。具体金额结合矿山规模与产线配置在商务阶段细化。
|
||||||
|
|
||||||
|
# 效益分析
|
||||||
|
|
||||||
|
- **经济效益**:减少入磨量,降低能耗与药剂成本;提升精矿品位与回收率。
|
||||||
|
- **环保效益**:减少尾矿产生量,降低固废处置压力。
|
||||||
|
- **社会效益**:支撑绿色矿山建设,提升企业技术形象。
|
||||||
|
|
||||||
|
# 风险分析与对策
|
||||||
|
|
||||||
|
| 风险 | 对策 |
|
||||||
|
| ---- | ---- |
|
||||||
|
| 原料波动影响模型稳定性 | 持续采样标注与模型迭代;异常降级策略 |
|
||||||
|
| 现场交付周期 | 标准化模块与运维工具;阶段里程碑管控 |
|
||||||
|
| 客户接受度 | 试点数据透明展示;可量化的效益测算 |
|
||||||
|
|
||||||
|
# 结论
|
||||||
|
|
||||||
|
综合技术验证、市场需求与实施条件,本项目具备可行性。建议推进试点产线建设,以现场数据支撑后续规模化复制。
|
||||||
38
feasibility/data/code.typ
Normal file
38
feasibility/data/code.typ
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#import "@preview/codly:1.3.0": *
|
||||||
|
#import "@preview/codly-languages:0.1.10": codly-languages
|
||||||
|
#import "theme.typ": *
|
||||||
|
|
||||||
|
#let codly-init-rule = codly-init.with()
|
||||||
|
|
||||||
|
#let codly-config = codly(
|
||||||
|
languages: codly-languages,
|
||||||
|
fill: code-block-fill,
|
||||||
|
radius: code-block-radius,
|
||||||
|
stroke: none,
|
||||||
|
zebra-fill: none,
|
||||||
|
number-format: none,
|
||||||
|
display-icon: false,
|
||||||
|
display-name: true,
|
||||||
|
default-color: color-body,
|
||||||
|
lang-stroke: (_) => none,
|
||||||
|
lang-fill: (_) => code-block-fill,
|
||||||
|
lang-radius: 0pt,
|
||||||
|
)
|
||||||
|
|
||||||
|
/// 与 codly 配合的语法高亮色(须在 codly-init 之后注册)
|
||||||
|
#let code-token-highlight-init(doc) = {
|
||||||
|
show raw.where(block: true): it => {
|
||||||
|
show "keyword": set text(fill: code-token-keyword)
|
||||||
|
show "comment": set text(fill: code-token-comment)
|
||||||
|
show "string": set text(fill: code-token-string)
|
||||||
|
show "number": set text(fill: code-token-number)
|
||||||
|
show "builtin": set text(fill: code-token-function)
|
||||||
|
show "function": set text(fill: code-token-function)
|
||||||
|
show "decor": set text(fill: code-token-function)
|
||||||
|
show "operator": set text(fill: code-token-operator)
|
||||||
|
show "punctuation": set text(fill: code-token-operator)
|
||||||
|
set text(fill: color-body)
|
||||||
|
it
|
||||||
|
}
|
||||||
|
doc
|
||||||
|
}
|
||||||
@ -1,10 +1,10 @@
|
|||||||
// =============================================================================
|
// =============================================================================
|
||||||
// 技术报告 — 默认值(正文在 content/report.md,YAML 可覆盖下列字段)
|
// 可行性报告 — 默认值(正文在 content/report.md,YAML 可覆盖下列字段)
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
#let default-brand = "GreLin"
|
#let default-brand = "GreLin"
|
||||||
#let default-company = "西安高岭绿能科技有限公司"
|
#let default-company = "西安高岭绿能科技有限公司"
|
||||||
#let default-title = "智能矿石分选系统技术报告"
|
#let default-title = "智能矿石分选系统建设项目"
|
||||||
#let default-version = "v1.0"
|
#let default-version = "v1.0"
|
||||||
#let default-date = "2026 年 6 月"
|
#let default-date = "2026 年 6 月"
|
||||||
|
|
||||||
51
feasibility/data/decor.typ
Normal file
51
feasibility/data/decor.typ
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#import "theme.typ": *
|
||||||
|
|
||||||
|
/// 点阵底纹
|
||||||
|
#let tech-dots(width: 100%, height: 100%, step: 10pt) = box(width: width, height: height, clip: true)[
|
||||||
|
#for x in range(40) {
|
||||||
|
for y in range(40) {
|
||||||
|
place(
|
||||||
|
left + top,
|
||||||
|
dx: x * step,
|
||||||
|
dy: y * step,
|
||||||
|
circle(radius: 0.35pt, fill: color-grid),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
/// 条形码条
|
||||||
|
#let tech-barcode(width, height, bars: 28) = box(width: width, height: height, clip: true)[
|
||||||
|
#for i in range(bars) {
|
||||||
|
let w = if calc.rem(i, 4) == 0 { 2.2pt } else if calc.rem(i, 2) == 0 { 1.4pt } else { 0.8pt }
|
||||||
|
place(
|
||||||
|
left + top,
|
||||||
|
dx: i * (width / bars),
|
||||||
|
box(width: w, height: 100%, fill: color-ink),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
/// 等宽标签
|
||||||
|
#let tech-label(body, fill: color-ink, size: 7pt) = text(
|
||||||
|
font: mono-font,
|
||||||
|
size: size,
|
||||||
|
fill: fill,
|
||||||
|
tracking: 0.14em,
|
||||||
|
)[#body]
|
||||||
|
|
||||||
|
/// 章节编号
|
||||||
|
#let section-tech-id(..nums) = {
|
||||||
|
let n = nums.pos()
|
||||||
|
let id = if n.len() == 1 {
|
||||||
|
let num = n.first()
|
||||||
|
if num < 10 { "0" + str(num) } else { str(num) }
|
||||||
|
} else if n.len() == 2 {
|
||||||
|
str(n.at(0)) + "." + str(n.at(1))
|
||||||
|
} else {
|
||||||
|
str(n.at(0)) + "." + str(n.at(1)) + "." + str(n.at(2))
|
||||||
|
}
|
||||||
|
box(fill: color-accent-surface, inset: (x: 5pt, y: 2pt))[
|
||||||
|
#text(font: mono-font, size: 7pt, weight: "bold", fill: color-ink)[#id]
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -18,7 +18,7 @@
|
|||||||
stroke: 1pt + color-brand,
|
stroke: 1pt + color-brand,
|
||||||
)
|
)
|
||||||
content((x + w / 2, 0.5), align(center + horizon)[
|
content((x + w / 2, 0.5), align(center + horizon)[
|
||||||
#text(font: body-font, size: text-xs, fill: color-body)[#label]
|
#text(font: body-font, size: 8pt, fill: color-body)[#label]
|
||||||
])
|
])
|
||||||
if i < labels.len() - 1 {
|
if i < labels.len() - 1 {
|
||||||
line(
|
line(
|
||||||
43
feasibility/data/glossary.typ
Normal file
43
feasibility/data/glossary.typ
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#import "@preview/glossarium:0.5.10": make-glossary, register-glossary, print-glossary, gls-long, gls-short
|
||||||
|
#import "theme.typ": *
|
||||||
|
|
||||||
|
#let glossary-entries = (
|
||||||
|
(
|
||||||
|
key: "hsi",
|
||||||
|
short: "HSI",
|
||||||
|
long: "高光谱成像",
|
||||||
|
description: "Hyperspectral Imaging,获取矿石连续波段光谱信息。",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
key: "onnx",
|
||||||
|
short: "ONNX",
|
||||||
|
long: "开放神经网络交换格式",
|
||||||
|
description: "Open Neural Network Exchange,用于跨平台模型推理部署。",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
key: "as-ratio",
|
||||||
|
short: "A/S",
|
||||||
|
long: "铝硅比",
|
||||||
|
description: "精矿品质评价的关键指标之一。",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
#let init-glossary(doc) = {
|
||||||
|
show: make-glossary
|
||||||
|
doc
|
||||||
|
}
|
||||||
|
|
||||||
|
#let register-report-glossary() = {
|
||||||
|
register-glossary(glossary-entries)
|
||||||
|
}
|
||||||
|
|
||||||
|
#let print-glossary-block() = {
|
||||||
|
pagebreak(weak: true)
|
||||||
|
block(width: 100%, above: space-chapter)[
|
||||||
|
#box(width: 100%, fill: color-accent-surface, inset: (x: 10pt, y: 6pt))[
|
||||||
|
#text(font: heading-font, size: size-h1, weight: "black", fill: color-ink)[术语与缩写]
|
||||||
|
]
|
||||||
|
#v(space-block)
|
||||||
|
#print-glossary(glossary-entries, show-all: true)
|
||||||
|
]
|
||||||
|
}
|
||||||
148
feasibility/data/layout.typ
Normal file
148
feasibility/data/layout.typ
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
#import "theme.typ": *
|
||||||
|
#import "logo.typ": grelin-logo, cover-index-badge
|
||||||
|
#import "decor.typ": tech-dots, tech-barcode, tech-label
|
||||||
|
|
||||||
|
#let format-cover-date(date) = {
|
||||||
|
let parts = date.split("-")
|
||||||
|
if parts.len() == 3 {
|
||||||
|
parts.at(0) + "." + parts.at(1) + "." + parts.at(2)
|
||||||
|
} else {
|
||||||
|
date
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#let cover-meta-strip(meta) = box(
|
||||||
|
width: 100%,
|
||||||
|
fill: color-ink,
|
||||||
|
inset: (x: 12pt, y: 8pt),
|
||||||
|
)[
|
||||||
|
#grid(
|
||||||
|
columns: (1fr, auto, 1fr, auto, 1fr),
|
||||||
|
column-gutter: 12pt,
|
||||||
|
align: horizon,
|
||||||
|
tech-label("VERSION", fill: color-accent, size: 6.5pt),
|
||||||
|
text(font: mono-font, size: 8pt, fill: white)[#meta.version],
|
||||||
|
tech-label("DATE", fill: color-accent, size: 6.5pt),
|
||||||
|
text(font: mono-font, size: 8pt, fill: white)[#format-cover-date(meta.date)],
|
||||||
|
align(right)[
|
||||||
|
tech-label("STATUS · DRAFT", fill: color-accent, size: 6.5pt)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
#let cover-block(meta) = {
|
||||||
|
pagebreak(weak: true)
|
||||||
|
block(width: 100%, below: space-chapter)[
|
||||||
|
#box(width: 100%, height: cover-block-height, fill: white)[
|
||||||
|
#place(top + left)[#grelin-logo()]
|
||||||
|
#place(top + right)[#cover-index-badge("01")]
|
||||||
|
|
||||||
|
#place(left + top, dy: 52pt)[#tech-barcode(14pt, 120pt, bars: 5)]
|
||||||
|
#place(right + top, dy: 72pt)[
|
||||||
|
#rotate(-90deg, reflow: true)[
|
||||||
|
#tech-label("FEASIBILITY REPORT", fill: color-caption, size: 6.5pt)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
#place(left + top, dx: 28pt, dy: 100pt)[
|
||||||
|
#box(width: 88%, height: 130pt, clip: true)[#tech-dots(width: 100%, height: 100%, step: 11pt)]
|
||||||
|
]
|
||||||
|
|
||||||
|
#place(left + top, dx: 24pt, dy: 168pt)[
|
||||||
|
#box(width: 92%, fill: color-accent-surface, inset: (x: 16pt, y: 18pt))[
|
||||||
|
#text(
|
||||||
|
font: heading-font,
|
||||||
|
size: size-cover-title,
|
||||||
|
weight: "black",
|
||||||
|
fill: color-ink,
|
||||||
|
hyphenate: false,
|
||||||
|
)[#meta.title]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
#place(left + bottom, dy: -36pt)[
|
||||||
|
#box(width: 100%)[#cover-meta-strip(meta)]
|
||||||
|
]
|
||||||
|
|
||||||
|
#place(left + bottom, dy: -8pt)[
|
||||||
|
#tech-barcode(100%, 10pt, bars: 48)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
pagebreak()
|
||||||
|
}
|
||||||
|
|
||||||
|
#let accent-line() = box(width: 100%, height: 2pt, fill: color-ink)
|
||||||
|
|
||||||
|
#let summary-block(meta) = {
|
||||||
|
if meta.summary != "" {
|
||||||
|
block(width: 100%, above: space-block, below: space-chapter)[
|
||||||
|
#box(
|
||||||
|
width: 100%,
|
||||||
|
fill: white,
|
||||||
|
stroke: 1.5pt + color-ink,
|
||||||
|
inset: summary-inset,
|
||||||
|
)[
|
||||||
|
#box(width: 100%, fill: color-accent-surface, inset: (x: 10pt, y: 5pt))[
|
||||||
|
#tech-label("ABSTRACT", fill: color-ink, size: 7pt)
|
||||||
|
]
|
||||||
|
#v(10pt)
|
||||||
|
#text(font: heading-font, size: size-h2, weight: "black", fill: color-ink)[摘要]
|
||||||
|
#v(space-block)
|
||||||
|
#set par(leading: leading-summary, justify: true)
|
||||||
|
#set text(size: size-body, fill: color-body)
|
||||||
|
#meta.summary
|
||||||
|
#v(space-section)
|
||||||
|
#grid(
|
||||||
|
columns: (auto, 1fr, auto, 1fr),
|
||||||
|
column-gutter: 8pt,
|
||||||
|
align: horizon,
|
||||||
|
tech-label("DATE", size: 6.5pt),
|
||||||
|
text(font: mono-font, size: size-meta, fill: color-body)[#meta.date],
|
||||||
|
tech-label("ORG", size: 6.5pt),
|
||||||
|
text(font: mono-font, size: size-meta, fill: color-body)[#meta.company],
|
||||||
|
)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#let page-footer() = context {
|
||||||
|
grid(
|
||||||
|
columns: (auto, 1fr, auto),
|
||||||
|
align: horizon,
|
||||||
|
tech-barcode(36pt, 8pt, bars: 10),
|
||||||
|
box(width: 100%, height: 1pt, fill: color-ink),
|
||||||
|
box(fill: color-ink, inset: (x: 8pt, y: 3pt))[
|
||||||
|
#text(font: mono-font, size: 8pt, fill: color-accent)[
|
||||||
|
#counter(page).display("1")
|
||||||
|
#h(0.12em)
|
||||||
|
#sym.slash
|
||||||
|
#h(0.12em)
|
||||||
|
#counter(page).final().first()
|
||||||
|
]
|
||||||
|
],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#let page-accent-bar() = place(
|
||||||
|
left + top,
|
||||||
|
tech-barcode(page-accent-bar-width, 100%, bars: 4),
|
||||||
|
)
|
||||||
|
|
||||||
|
#let page-header(meta) = [
|
||||||
|
#grid(
|
||||||
|
columns: (auto, 1fr, auto),
|
||||||
|
column-gutter: 8pt,
|
||||||
|
align: horizon,
|
||||||
|
box(fill: color-accent-surface, inset: (x: 6pt, y: 2pt))[
|
||||||
|
#text(font: mono-font, size: 7pt, weight: "bold", fill: color-ink)[#upper(meta.brand)]
|
||||||
|
],
|
||||||
|
box(width: 100%, height: 1pt, fill: color-ink),
|
||||||
|
align(right)[
|
||||||
|
#text(font: mono-font, size: 7pt, fill: color-caption)[#meta.title]
|
||||||
|
],
|
||||||
|
)
|
||||||
|
#v(6pt)
|
||||||
|
#accent-line()
|
||||||
|
]
|
||||||
37
feasibility/data/logo.typ
Normal file
37
feasibility/data/logo.typ
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#import "theme.typ": *
|
||||||
|
#import "decor.typ": tech-label
|
||||||
|
|
||||||
|
/// Logo:品牌蓝块 + 白色折线图形 + GreLin | Tech
|
||||||
|
#let grelin-logo(
|
||||||
|
primary: "GreLin",
|
||||||
|
secondary: "Tech",
|
||||||
|
) = grid(
|
||||||
|
columns: (auto, auto),
|
||||||
|
column-gutter: 10pt,
|
||||||
|
align: horizon,
|
||||||
|
box(width: 34pt, height: 34pt, fill: color-brand)[
|
||||||
|
#place(left + top, dx: 7pt, dy: 8pt, box(width: 14pt, height: 3pt, fill: white))
|
||||||
|
#place(left + top, dx: 7pt, dy: 14pt, box(width: 3pt, height: 14pt, fill: white))
|
||||||
|
#place(left + top, dx: 18pt, dy: 14pt, box(width: 9pt, height: 3pt, fill: white))
|
||||||
|
#place(left + top, dx: 18pt, dy: 17pt, box(width: 3pt, height: 11pt, fill: white))
|
||||||
|
],
|
||||||
|
grid(
|
||||||
|
columns: (auto, auto, auto),
|
||||||
|
column-gutter: 7pt,
|
||||||
|
align: horizon,
|
||||||
|
text(font: heading-font, size: 12pt, weight: "black", fill: color-ink, tracking: 0.04em)[#primary],
|
||||||
|
box(width: 1.2pt, height: 1em, fill: color-ink),
|
||||||
|
text(font: heading-font, size: 12pt, weight: "black", fill: color-ink, tracking: 0.16em)[#secondary],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
#let cover-index-badge(index) = box(
|
||||||
|
width: 58pt,
|
||||||
|
height: 58pt,
|
||||||
|
stroke: 2pt + color-ink,
|
||||||
|
fill: white,
|
||||||
|
)[
|
||||||
|
#align(center + horizon)[
|
||||||
|
#text(font: mono-font, size: size-cover-index, weight: "black", fill: color-ink)[#index]
|
||||||
|
]
|
||||||
|
]
|
||||||
@ -1,40 +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
|
||||||
#let underline-accent(body) = underline(
|
|
||||||
body,
|
|
||||||
stroke: 1.5pt + color-primary,
|
|
||||||
offset: 4pt,
|
|
||||||
evade: true,
|
|
||||||
)
|
|
||||||
|
|
||||||
#let text-highlight(body) = highlight(
|
|
||||||
body,
|
|
||||||
fill: color-accent-surface,
|
|
||||||
top-edge: "ascender",
|
|
||||||
bottom-edge: "descender",
|
|
||||||
radius: tw(0.5),
|
|
||||||
)
|
|
||||||
|
|
||||||
#let parse-report-date(raw) = {
|
|
||||||
if type(raw) == datetime {
|
|
||||||
raw
|
|
||||||
} else if type(raw) == str {
|
|
||||||
let parts = raw.split("-")
|
|
||||||
if parts.len() == 3 {
|
|
||||||
datetime(
|
|
||||||
year: int(parts.at(0)),
|
|
||||||
month: int(parts.at(1)),
|
|
||||||
day: int(parts.at(2)),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
none
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
none
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#let source-dir(path) = {
|
#let source-dir(path) = {
|
||||||
let parts = path.split("/")
|
let parts = path.split("/")
|
||||||
@ -90,7 +57,6 @@
|
|||||||
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),
|
||||||
160
feasibility/data/styling.typ
Normal file
160
feasibility/data/styling.typ
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
#import "theme.typ": *
|
||||||
|
#import "decor.typ": section-tech-id, tech-label
|
||||||
|
|
||||||
|
#let underline-accent(body) = underline(
|
||||||
|
body,
|
||||||
|
stroke: underline-stroke,
|
||||||
|
offset: underline-offset,
|
||||||
|
evade: true,
|
||||||
|
)
|
||||||
|
|
||||||
|
#let heading-number(it) = {
|
||||||
|
if it.numbering != none {
|
||||||
|
counter(heading).display(it.numbering)
|
||||||
|
h(heading-number-gap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#let report-heading-numbering(..nums) = {
|
||||||
|
let n = nums.pos()
|
||||||
|
if n.len() == 1 {
|
||||||
|
numbering("1.", n.first())
|
||||||
|
} else if n.len() == 2 {
|
||||||
|
numbering("1.1", n.at(0), n.at(1))
|
||||||
|
} else {
|
||||||
|
numbering("1.1.1", ..n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#let grelin-h1(it) = block(
|
||||||
|
width: 100%,
|
||||||
|
above: space-chapter,
|
||||||
|
below: space-block,
|
||||||
|
)[
|
||||||
|
#grid(
|
||||||
|
columns: (auto, 1fr),
|
||||||
|
column-gutter: 8pt,
|
||||||
|
align: horizon,
|
||||||
|
context section-tech-id(..counter(heading).get()),
|
||||||
|
box(width: 100%, fill: color-accent-surface, inset: (x: 8pt, y: 4pt))[
|
||||||
|
#text(font: heading-font, size: size-h1, weight: "black", fill: color-ink)[
|
||||||
|
#heading-number(it)
|
||||||
|
#it.body
|
||||||
|
]
|
||||||
|
],
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
#let grelin-h2(it) = block(width: 100%, above: space-section, below: space-inline)[
|
||||||
|
#grid(
|
||||||
|
columns: (auto, 1fr),
|
||||||
|
column-gutter: 8pt,
|
||||||
|
align: horizon,
|
||||||
|
box(width: 3pt, height: 1em, fill: color-ink),
|
||||||
|
text(font: heading-font, size: size-h2, weight: "bold", fill: color-ink)[
|
||||||
|
#heading-number(it)
|
||||||
|
#it.body
|
||||||
|
],
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
#let grelin-h3(it) = block(width: 100%, above: space-block, below: space-micro)[
|
||||||
|
#grid(
|
||||||
|
columns: (auto, 1fr),
|
||||||
|
column-gutter: 6pt,
|
||||||
|
align: horizon,
|
||||||
|
tech-label("///", size: 6.5pt),
|
||||||
|
text(font: heading-font, size: size-h3, weight: "bold", fill: color-ink)[
|
||||||
|
#heading-number(it)
|
||||||
|
#it.body
|
||||||
|
],
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
#let grelin-image(it) = block(
|
||||||
|
width: 100%,
|
||||||
|
above: space-figure-before,
|
||||||
|
below: space-figure-after,
|
||||||
|
)[
|
||||||
|
#align(center)[
|
||||||
|
#box(width: image-max-width, stroke: 1pt + color-ink)[
|
||||||
|
#set image(width: 100%, fit: "contain")
|
||||||
|
#it
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
#let grelin-table(it) = block(
|
||||||
|
width: 100%,
|
||||||
|
above: space-figure-before,
|
||||||
|
below: space-figure-after,
|
||||||
|
)[
|
||||||
|
#it
|
||||||
|
]
|
||||||
|
|
||||||
|
#let grelin-figure(it) = block(
|
||||||
|
width: 100%,
|
||||||
|
above: space-figure-before,
|
||||||
|
below: space-figure-after,
|
||||||
|
)[
|
||||||
|
#align(center)[
|
||||||
|
#set image(width: image-max-width, fit: "contain")
|
||||||
|
#set text(size: size-caption, fill: color-caption)
|
||||||
|
#it
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
#let grelin-blockquote(it) = block(
|
||||||
|
width: 100%,
|
||||||
|
above: space-block,
|
||||||
|
below: space-block,
|
||||||
|
inset: (left: blockquote-inset),
|
||||||
|
stroke: (left: blockquote-stroke),
|
||||||
|
fill: white,
|
||||||
|
)[
|
||||||
|
#set par(leading: leading-body, justify: true)
|
||||||
|
#set text(fill: color-quote)
|
||||||
|
#it
|
||||||
|
]
|
||||||
|
|
||||||
|
#let grelin-inline-code(it) = box(
|
||||||
|
fill: code-inline-fill,
|
||||||
|
inset: code-inline-inset,
|
||||||
|
stroke: 0.8pt + color-ink,
|
||||||
|
)[
|
||||||
|
#set text(font: mono-font, size: size-body, fill: color-code-inline)
|
||||||
|
#it
|
||||||
|
]
|
||||||
|
|
||||||
|
#let apply-report-styling(body) = {
|
||||||
|
set heading(numbering: report-heading-numbering)
|
||||||
|
set text(size: size-table)
|
||||||
|
set table(
|
||||||
|
stroke: (x, y) => (
|
||||||
|
top: if y == 0 { 1.5pt + color-ink } else { none },
|
||||||
|
bottom: if y == 0 { 0.8pt + color-ink } else { none },
|
||||||
|
),
|
||||||
|
inset: table-inset,
|
||||||
|
align: (col, row) => if col == 0 { left + horizon } else { center + horizon },
|
||||||
|
fill: (col, row) => {
|
||||||
|
if row == 0 {
|
||||||
|
table-header-fill
|
||||||
|
} else if calc.rem(row, 2) == 0 {
|
||||||
|
table-zebra-fill
|
||||||
|
} else {
|
||||||
|
white
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
show heading.where(level: 1): grelin-h1
|
||||||
|
show heading.where(level: 2): grelin-h2
|
||||||
|
show heading.where(level: 3): grelin-h3
|
||||||
|
show image: grelin-image
|
||||||
|
show table.cell: set text(fill: table-data-text)
|
||||||
|
show table.cell.where(y: 0): set text(weight: "bold", fill: color-ink)
|
||||||
|
show table: grelin-table
|
||||||
|
show figure: grelin-figure
|
||||||
|
show quote.where(block: true): grelin-blockquote
|
||||||
|
show raw.where(block: false): grelin-inline-code
|
||||||
|
body
|
||||||
|
}
|
||||||
102
feasibility/data/theme.typ
Normal file
102
feasibility/data/theme.typ
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
#import "../../brand/colors.typ": *
|
||||||
|
|
||||||
|
// 可行性报告配色:品牌蓝 · 纯黑 · 冷灰
|
||||||
|
#let color-accent = color-brand
|
||||||
|
#let color-accent-surface = color-brand-surface
|
||||||
|
#let color-heading = color-brand
|
||||||
|
#let color-accent-line = color-ink
|
||||||
|
#let color-divider = rgb(205, 205, 205)
|
||||||
|
#let color-caption = rgb(110, 110, 110)
|
||||||
|
#let color-quote = rgb(90, 90, 90)
|
||||||
|
#let color-code-lang = rgb(90, 90, 90)
|
||||||
|
#let color-code-inline = color-ink
|
||||||
|
#let color-header = color-ink
|
||||||
|
#let color-page = rgb(238, 238, 238)
|
||||||
|
#let color-bar-bg = rgb(248, 248, 248)
|
||||||
|
#let color-grid = rgb(220, 220, 220)
|
||||||
|
|
||||||
|
// 代码块语法高亮
|
||||||
|
#let code-token-keyword = color-ink
|
||||||
|
#let code-token-comment = rgb(130, 130, 130)
|
||||||
|
#let code-token-string = rgb(40, 40, 40)
|
||||||
|
#let code-token-number = rgb(70, 70, 70)
|
||||||
|
#let code-token-function = color-ink
|
||||||
|
#let code-token-operator = rgb(100, 100, 100)
|
||||||
|
|
||||||
|
#let heading-font = ("Microsoft YaHei", "Segoe UI", "Segoe UI Emoji")
|
||||||
|
#let body-font = ("Microsoft YaHei UI", "Microsoft YaHei", "Segoe UI", "Segoe UI Emoji")
|
||||||
|
#let mono-font = ("Consolas", "Cascadia Mono", "Microsoft YaHei UI")
|
||||||
|
|
||||||
|
// =====================================================================
|
||||||
|
// GreLin Feasibility Report · Design Tokens
|
||||||
|
// =====================================================================
|
||||||
|
|
||||||
|
// --- 字号 ---
|
||||||
|
#let size-title = 22pt
|
||||||
|
#let size-cover-title = 34pt
|
||||||
|
#let size-cover-index = 52pt
|
||||||
|
#let size-h1 = 14pt
|
||||||
|
#let size-h2 = 12pt
|
||||||
|
#let size-h3 = 11pt
|
||||||
|
#let size-body = 10.5pt
|
||||||
|
#let size-meta = 9pt
|
||||||
|
#let size-table = 9pt
|
||||||
|
#let size-caption = size-meta
|
||||||
|
|
||||||
|
// --- 行距 ---
|
||||||
|
#let leading-body = 12.5pt
|
||||||
|
#let leading-summary = leading-body
|
||||||
|
|
||||||
|
// --- 间距 ---
|
||||||
|
#let space-none = 0pt
|
||||||
|
#let space-micro = 4pt
|
||||||
|
#let space-inline = 6pt
|
||||||
|
#let space-block = 10pt
|
||||||
|
#let space-section = 12pt
|
||||||
|
#let space-chapter = 18pt
|
||||||
|
#let space-figure-before = space-block
|
||||||
|
#let space-figure-after = space-section
|
||||||
|
#let space-cover-line = 3pt
|
||||||
|
#let space-cover-title = 3pt
|
||||||
|
#let space-cover-meta = 6pt
|
||||||
|
#let cover-block-height = 19.5cm
|
||||||
|
|
||||||
|
// --- 线条 / 边框 ---
|
||||||
|
#let underline-stroke = 2pt + color-accent
|
||||||
|
#let underline-offset = 5pt
|
||||||
|
#let heading-number-gap = 0.35em
|
||||||
|
#let stroke-accent = 1.5pt + color-ink
|
||||||
|
#let summary-radius = 0pt
|
||||||
|
#let summary-inset = 14pt
|
||||||
|
|
||||||
|
// --- 页面 ---
|
||||||
|
#let page-margin = (
|
||||||
|
top: 2.5cm,
|
||||||
|
bottom: 2.5cm,
|
||||||
|
left: 2.5cm,
|
||||||
|
right: 2.5cm,
|
||||||
|
)
|
||||||
|
#let page-header-ascent = 1.0cm
|
||||||
|
#let page-footer-descent = 0.8cm
|
||||||
|
#let page-accent-bar-width = 10pt
|
||||||
|
|
||||||
|
// --- 表格 ---
|
||||||
|
#let table-zebra-fill = color-brand-tint
|
||||||
|
#let table-header-fill = color-brand-surface
|
||||||
|
#let table-data-text = rgb(50, 50, 50)
|
||||||
|
#let table-inset = (x: 10pt, y: 6pt)
|
||||||
|
|
||||||
|
// --- 图片 ---
|
||||||
|
#let image-max-width = 100%
|
||||||
|
|
||||||
|
// --- 代码 ---
|
||||||
|
#let code-block-inset = 10pt
|
||||||
|
#let code-block-radius = 0pt
|
||||||
|
#let code-block-fill = rgb(255, 255, 255)
|
||||||
|
#let code-inline-fill = rgb(255, 255, 255)
|
||||||
|
#let code-inline-inset = (x: 5pt, y: 0.12em)
|
||||||
|
#let code-inline-radius = 0pt
|
||||||
|
|
||||||
|
// --- 引用 ---
|
||||||
|
#let blockquote-inset = 10pt
|
||||||
|
#let blockquote-stroke = 3pt + color-accent
|
||||||
53
feasibility/report.typ
Normal file
53
feasibility/report.typ
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#import "data/config.typ": *
|
||||||
|
#import "data/theme.typ": *
|
||||||
|
#import "data/glossary.typ": init-glossary, print-glossary-block, register-report-glossary, gls-long, gls-short
|
||||||
|
#import "data/diagrams.typ": ore-sorting-flow
|
||||||
|
#import "data/code.typ": codly-init-rule, codly-config, code-token-highlight-init
|
||||||
|
#import "data/styling.typ": apply-report-styling
|
||||||
|
#import "data/layout.typ": cover-block, summary-block, page-header, page-footer, page-accent-bar
|
||||||
|
#import "data/md.typ": load-report-md
|
||||||
|
|
||||||
|
#show: codly-init-rule
|
||||||
|
#show: code-token-highlight-init
|
||||||
|
#show: init-glossary
|
||||||
|
#codly-config
|
||||||
|
|
||||||
|
#register-report-glossary()
|
||||||
|
|
||||||
|
#let report = load-report-md(
|
||||||
|
read(content-path),
|
||||||
|
source-path: content-path,
|
||||||
|
extra-scope: (
|
||||||
|
ore-sorting-flow: ore-sorting-flow,
|
||||||
|
gls-long: gls-long,
|
||||||
|
gls-short: gls-short,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
#let meta = report.metadata
|
||||||
|
|
||||||
|
#set page(
|
||||||
|
paper: "a4",
|
||||||
|
margin: page-margin,
|
||||||
|
header-ascent: page-header-ascent,
|
||||||
|
footer-descent: page-footer-descent,
|
||||||
|
fill: color-page,
|
||||||
|
background: page-accent-bar(),
|
||||||
|
header: context {
|
||||||
|
if counter(page).get().first() > 1 {
|
||||||
|
page-header(meta)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
footer: context {
|
||||||
|
if counter(page).get().first() > 1 {
|
||||||
|
page-footer()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
#set text(font: body-font, lang: "zh", size: size-body, fill: color-body)
|
||||||
|
#set par(leading: leading-body, justify: true)
|
||||||
|
|
||||||
|
#cover-block(meta)
|
||||||
|
#summary-block(meta)
|
||||||
|
#apply-report-styling(report.body)
|
||||||
|
#print-glossary-block()
|
||||||
5915
feasibility/sample.pdf
Normal file
5915
feasibility/sample.pdf
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,22 +0,0 @@
|
|||||||
# Presentation · PPT 演示模板
|
|
||||||
|
|
||||||
GreLin 16:9 演示文稿 Typst 模板(占位,待完善)。
|
|
||||||
|
|
||||||
入口:`deck.typ` · 内容:`data/config.typ` · 样式:`data/theme.typ`
|
|
||||||
|
|
||||||
## 目录结构
|
|
||||||
|
|
||||||
```
|
|
||||||
presentation/
|
|
||||||
├── deck.typ # 入口
|
|
||||||
├── data/
|
|
||||||
│ ├── config.typ # ★ 标题、作者、幻灯片内容
|
|
||||||
│ └── theme.typ # 设计 token
|
|
||||||
└── assets/ # 图片等资源
|
|
||||||
```
|
|
||||||
|
|
||||||
## 编译
|
|
||||||
|
|
||||||
```bash
|
|
||||||
typst compile --root . presentation/deck.typ presentation/sample.pdf
|
|
||||||
```
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
#let meta = (
|
|
||||||
title: "GreLin 演示标题",
|
|
||||||
subtitle: "副标题 / 日期 / 演讲者",
|
|
||||||
author: "GreLin",
|
|
||||||
)
|
|
||||||
|
|
||||||
#let slides = (
|
|
||||||
(
|
|
||||||
title: "章节一",
|
|
||||||
body: "在此编写第一页正文。",
|
|
||||||
),
|
|
||||||
(
|
|
||||||
title: "章节二",
|
|
||||||
body: "在此编写第二页正文。",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
#import "/brand/colors.typ": *
|
|
||||||
|
|
||||||
#let color-primary = color-brand
|
|
||||||
#let color-heading = color-ink
|
|
||||||
#let color-text = color-body
|
|
||||||
#let color-text-light = color-muted
|
|
||||||
|
|
||||||
#let body-font = ("Segoe UI", "Microsoft YaHei UI", "Microsoft YaHei")
|
|
||||||
#let heading-font = body-font
|
|
||||||
|
|
||||||
#let size-title = 36pt
|
|
||||||
#let size-subtitle = 18pt
|
|
||||||
#let size-body = 16pt
|
|
||||||
#let size-section = 24pt
|
|
||||||
|
|
||||||
#let leading-body = size-body * 1.5
|
|
||||||
|
|
||||||
#let slide-margin = (
|
|
||||||
top: 2cm,
|
|
||||||
bottom: 2cm,
|
|
||||||
left: 2.5cm,
|
|
||||||
right: 2.5cm,
|
|
||||||
)
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
#import "data/config.typ": *
|
|
||||||
#import "data/theme.typ": *
|
|
||||||
|
|
||||||
#set page(
|
|
||||||
paper: "presentation-16-9",
|
|
||||||
margin: slide-margin,
|
|
||||||
fill: color-page,
|
|
||||||
)
|
|
||||||
|
|
||||||
#set text(
|
|
||||||
font: body-font,
|
|
||||||
size: size-body,
|
|
||||||
fill: color-text,
|
|
||||||
lang: "zh",
|
|
||||||
)
|
|
||||||
|
|
||||||
#set par(leading: leading-body, justify: false)
|
|
||||||
|
|
||||||
#align(center + horizon)[
|
|
||||||
#text(font: heading-font, size: size-title, weight: "bold", fill: color-primary)[#meta.title]
|
|
||||||
#v(0.8em)
|
|
||||||
#text(size: size-subtitle, fill: color-text-light)[#meta.subtitle]
|
|
||||||
]
|
|
||||||
|
|
||||||
#pagebreak()
|
|
||||||
|
|
||||||
#for slide in slides [
|
|
||||||
#text(font: heading-font, size: size-section, weight: "bold", fill: color-heading)[#slide.title]
|
|
||||||
#v(1em)
|
|
||||||
#slide.body
|
|
||||||
#pagebreak()
|
|
||||||
]
|
|
||||||
Binary file not shown.
12
resume-career/local/README.md
Normal file
12
resume-career/local/README.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# 本地简历(不提交 Git)
|
||||||
|
|
||||||
|
在此目录为每位同学生成子文件夹,例如 `local/zhangsan/`:
|
||||||
|
|
||||||
|
```
|
||||||
|
local/zhangsan/
|
||||||
|
├── config.typ # 从 ../data/config.typ 复制后改内容
|
||||||
|
├── photo.jpeg # 证件照;config 里写 photo-path: "../photo.jpeg"
|
||||||
|
└── compile.ps1 # 可选:编译脚本
|
||||||
|
```
|
||||||
|
|
||||||
|
`compile.ps1` 可参考 [`resume-bp/local/wenzf/compile.ps1`](../../resume-bp/local/wenzf/compile.ps1),将 `$resumeRoot` 指向 `resume-career` 即可。
|
||||||
@ -1,49 +0,0 @@
|
|||||||
# Tech Report · 技术报告模板
|
|
||||||
|
|
||||||
GreLin 技术报告 Typst 模板:**封面**与**目录**见 `data/cover.typ`、`data/toc.typ`;**正文**见 `data/body.typ`。
|
|
||||||
|
|
||||||
## 快速开始
|
|
||||||
|
|
||||||
1. 编辑 [`content/report.md`](content/report.md)
|
|
||||||
2. 打开 [`report.typ`](report.typ) 预览或导出 PDF
|
|
||||||
|
|
||||||
```bash
|
|
||||||
typst compile tech-report/report.typ tech-report/sample.pdf --root .
|
|
||||||
```
|
|
||||||
|
|
||||||
## 目录结构
|
|
||||||
|
|
||||||
| 文件 | 说明 |
|
|
||||||
|------|------|
|
|
||||||
| [`content/report.md`](content/report.md) | **主编辑入口**:YAML 元数据 + 正文 |
|
|
||||||
| [`content/assets/`](content/assets/) | 图片资源 |
|
|
||||||
| [`data/config.typ`](data/config.typ) | 默认公司名、标题等 |
|
|
||||||
| [`data/theme.typ`](data/theme.typ) | 字号、行距、GreLin 品牌色 |
|
|
||||||
| [`data/cover.typ`](data/cover.typ) | 封面装饰与版式 |
|
|
||||||
| [`data/body.typ`](data/body.typ) | 正文版式(标题、表格、代码、页脚) |
|
|
||||||
| [`report.typ`](report.typ) | 编译入口 |
|
|
||||||
|
|
||||||
## YAML 元数据
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
---
|
|
||||||
title: 某某矿山智能分选技术报告
|
|
||||||
brand: GreLin
|
|
||||||
company: 西安高岭绿能科技有限公司
|
|
||||||
date: 2026-06-22
|
|
||||||
version: v1.0
|
|
||||||
summary: |
|
|
||||||
摘要正文……
|
|
||||||
---
|
|
||||||
```
|
|
||||||
|
|
||||||
## 依赖
|
|
||||||
|
|
||||||
| 包 | 用途 |
|
|
||||||
|----|------|
|
|
||||||
| [cmarker](https://typst.app/universe/package/cmarker) | Markdown → Typst |
|
|
||||||
| [codly](https://typst.app/universe/package/codly) | 代码块高亮 |
|
|
||||||
|
|
||||||
## 样式参考
|
|
||||||
|
|
||||||
封面与目录样式见 `data/cover.typ`、`data/toc.typ`;正文样式见 `data/body.typ`、`data/theme.typ`。
|
|
||||||
@ -1,187 +0,0 @@
|
|||||||
---
|
|
||||||
title: "GreLin 技术报告\n模板使用说明"
|
|
||||||
company: 西安高岭绿能科技有限公司
|
|
||||||
date: 2026-06-22
|
|
||||||
version: v2.0
|
|
||||||
summary: |
|
|
||||||
本手册面向首次使用 GreLin 技术报告模板的同事,说明如何编辑 Markdown 正文、配置封面元数据、预览排版效果并导出 PDF。按章节操作即可完成一份符合 GreLin 版式规范的技术报告。
|
|
||||||
---
|
|
||||||
|
|
||||||
# 快速开始
|
|
||||||
|
|
||||||
技术报告的主编辑入口是 `tech-report/content/report.md`。你**几乎不需要修改 Typst 代码**,只需在该 Markdown 文件中撰写正文,并维护文件开头的 YAML 元数据。
|
|
||||||
|
|
||||||
推荐工作流如下:
|
|
||||||
|
|
||||||
1. 用 VS Code 或 Cursor 打开仓库,编辑 `content/report.md`。
|
|
||||||
2. 打开 `report.typ`,使用 Tinymist 扩展的 **Typst Preview** 实时预览。
|
|
||||||
3. 确认无误后,执行 **Typst Export PDF** 或使用命令行导出。
|
|
||||||
|
|
||||||
在项目根目录执行:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
typst compile --root . tech-report/report.typ tech-report/sample.pdf
|
|
||||||
```
|
|
||||||
|
|
||||||
> 提示:封面、目录、页码与正文样式已由模板封装;日常写作只需关注 `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` 字段;正文区不再重复「摘要」标题,且与第一章可在同一页连续排版。
|
|
||||||
- **目录**:由模板自动生成,仅列出正文章节;摘要不会出现在目录中。
|
|
||||||
|
|
||||||
# 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
|
|
||||||
# 示例:处理产线数据流
|
|
||||||
for sample in belt_stream:
|
|
||||||
grade = model.infer(sample)
|
|
||||||
valve.fire(grade)
|
|
||||||
```
|
|
||||||
|
|
||||||
# 高级功能
|
|
||||||
|
|
||||||
## 插入 Typst 组件
|
|
||||||
|
|
||||||
复杂图表或自定义组件可在 Markdown 中插入 Typst 代码:
|
|
||||||
|
|
||||||
<!--raw-typst #ore-sorting-flow()-->
|
|
||||||
|
|
||||||
如需新增组件,在 `data/` 下编写 Typst 函数,并在 `report.typ` 的 `extra-scope` 中注册后,即可用 `<!--raw-typst #函数名()-->` 调用。
|
|
||||||
|
|
||||||
# 版式说明
|
|
||||||
|
|
||||||
| 页面 | 边距 | 说明 |
|
|
||||||
| ---- | ---- | ---- |
|
|
||||||
| 封面 | 自定义 | 左侧蓝色色块贴边,见 `data/cover.typ` |
|
|
||||||
| 目录 | 2.5 cm | 较宽边距,便于大号章节编号排版 |
|
|
||||||
| 正文 | 2 cm | 摘要及正文内容使用较窄边距 |
|
|
||||||
|
|
||||||
正文无页眉;页码从正文第一章起算,格式为 `当前页 / 总页数`,位于页脚右侧。
|
|
||||||
|
|
||||||
# 常见问题
|
|
||||||
|
|
||||||
**Q:修改 Markdown 后预览没有更新?**
|
|
||||||
A:保存 `report.md` 后,Typst Preview 通常会自动刷新;若无反应,可关闭预览后重新打开 `report.typ`。
|
|
||||||
|
|
||||||
**Q:图片找不到?**
|
|
||||||
A:确认路径相对于 `content/report.md`,且文件位于 `content/assets/` 目录下。
|
|
||||||
|
|
||||||
**Q:想改主题色或字号?**
|
|
||||||
A:全局 token 在 `data/theme.typ`;正文组件样式在 `data/body.typ`;封面/目录分别在 `data/cover.typ`、`data/toc.typ`。品牌色也可在 `brand/colors.typ` 调整。
|
|
||||||
|
|
||||||
完成以上步骤后,你即可基于本模板快速产出 GreLin 风格的技术报告。祝写作顺利。
|
|
||||||
@ -1,186 +0,0 @@
|
|||||||
#import "theme.typ": *
|
|
||||||
|
|
||||||
#let page-numbering-started = state("page-numbering-started", false)
|
|
||||||
|
|
||||||
#let start-body-page-numbering() = {
|
|
||||||
page-numbering-started.update(true)
|
|
||||||
counter(page).update(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
#let report-body(
|
|
||||||
title: none,
|
|
||||||
author: none,
|
|
||||||
date: none,
|
|
||||||
paper-size: "a4",
|
|
||||||
language: "zh",
|
|
||||||
font-size: size-body,
|
|
||||||
leading-ratio: leading-ratio,
|
|
||||||
body-font: body-font,
|
|
||||||
heading-font: heading-font,
|
|
||||||
raw-font: mono-font,
|
|
||||||
margin-x: body-margin-x,
|
|
||||||
margin-y: body-margin-y,
|
|
||||||
accent-color: color-primary,
|
|
||||||
body-text-color: color-body-text,
|
|
||||||
body,
|
|
||||||
) = {
|
|
||||||
let scale = 1.25
|
|
||||||
let caption-size = font-size * calc.pow(scale, -1)
|
|
||||||
let lead-size = font-size * calc.pow(scale, 1)
|
|
||||||
let heading-size = font-size * calc.pow(scale, 2)
|
|
||||||
let line-height = font-size * leading-ratio
|
|
||||||
let muted-color = color.mix(
|
|
||||||
(rgb("#000000"), 5),
|
|
||||||
(rgb("#ffffff"), 3),
|
|
||||||
space: oklab,
|
|
||||||
)
|
|
||||||
|
|
||||||
set document(title: title, date: date)
|
|
||||||
if author != none {
|
|
||||||
set document(author: author)
|
|
||||||
}
|
|
||||||
|
|
||||||
set text(
|
|
||||||
font: body-font,
|
|
||||||
size: font-size,
|
|
||||||
fill: body-text-color,
|
|
||||||
lang: language,
|
|
||||||
)
|
|
||||||
show raw: set text(font: raw-font)
|
|
||||||
|
|
||||||
set par(
|
|
||||||
leading: line-height - font-size,
|
|
||||||
spacing: line-height,
|
|
||||||
justify: true,
|
|
||||||
)
|
|
||||||
|
|
||||||
set page(
|
|
||||||
paper: paper-size,
|
|
||||||
margin: (x: margin-x, top: margin-y, bottom: margin-y),
|
|
||||||
header: none,
|
|
||||||
footer: context {
|
|
||||||
v(line-height / 2)
|
|
||||||
if page-numbering-started.at(here()) {
|
|
||||||
align(right, text(
|
|
||||||
font: heading-font,
|
|
||||||
size: caption-size,
|
|
||||||
fill: muted-color,
|
|
||||||
counter(page).display("1 / 1", both: true),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
footer-descent: line-height,
|
|
||||||
)
|
|
||||||
|
|
||||||
let report-heading(it, size, above, below, title-fill: rgb("#000000")) = block(
|
|
||||||
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(font: heading-font, size: size, weight: "bold", fill: title-fill, it.body)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
show heading.where(level: 1): it => {
|
|
||||||
report-heading(it, heading-size, line-height * 2, line-height, title-fill: accent-color)
|
|
||||||
}
|
|
||||||
show heading.where(level: 2): it => {
|
|
||||||
report-heading(it, lead-size, line-height * 2, line-height * 0.85)
|
|
||||||
}
|
|
||||||
show heading.where(level: 3): it => {
|
|
||||||
report-heading(it, font-size, line-height, line-height * 0.75)
|
|
||||||
}
|
|
||||||
show heading.where(level: 4): it => {
|
|
||||||
report-heading(it, caption-size, line-height * 0.85, line-height * 0.65)
|
|
||||||
}
|
|
||||||
|
|
||||||
set list(
|
|
||||||
indent: 0pt,
|
|
||||||
body-indent: line-height / 2,
|
|
||||||
marker: text(font: heading-font, fill: accent-color, weight: "bold")[•],
|
|
||||||
)
|
|
||||||
set enum(
|
|
||||||
indent: 0pt,
|
|
||||||
body-indent: line-height / 2,
|
|
||||||
numbering: (..nums) => text(
|
|
||||||
font: heading-font,
|
|
||||||
fill: accent-color,
|
|
||||||
weight: "medium",
|
|
||||||
numbering("1.a.i.", ..nums),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
show quote.where(block: true): it => {
|
|
||||||
v(line-height * 0.75, weak: true)
|
|
||||||
block(width: 100%)[
|
|
||||||
#block(
|
|
||||||
width: 100%,
|
|
||||||
inset: (left: tw(3.5)),
|
|
||||||
stroke: (left: quote-bar-stroke + quote-bar-color),
|
|
||||||
)[
|
|
||||||
#text(font: body-font, fill: body-text-color, it.body)
|
|
||||||
]
|
|
||||||
]
|
|
||||||
v(line-height * 0.75, weak: true)
|
|
||||||
}
|
|
||||||
|
|
||||||
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(
|
|
||||||
stroke: none,
|
|
||||||
inset: (x: line-height / 2, y: line-height / 2),
|
|
||||||
fill: (x, y) => if y == 0 {
|
|
||||||
accent-color
|
|
||||||
} else if calc.even(y) {
|
|
||||||
color-block-bg
|
|
||||||
} else {
|
|
||||||
none
|
|
||||||
},
|
|
||||||
)
|
|
||||||
show table.cell.where(y: 0): it => {
|
|
||||||
text(font: heading-font, weight: "bold", size: caption-size, fill: white, it)
|
|
||||||
}
|
|
||||||
|
|
||||||
show raw.where(block: true): block.with(
|
|
||||||
inset: (x: line-height, y: line-height / 2),
|
|
||||||
width: 100%,
|
|
||||||
fill: color-block-bg,
|
|
||||||
radius: code-block-radius,
|
|
||||||
)
|
|
||||||
show raw.where(block: true): set par(justify: false)
|
|
||||||
show raw.where(block: false): box.with(
|
|
||||||
inset: (x: 3pt, y: 0pt),
|
|
||||||
outset: (y: 3pt),
|
|
||||||
fill: color-block-bg,
|
|
||||||
radius: code-inline-radius,
|
|
||||||
)
|
|
||||||
|
|
||||||
show link: it => {
|
|
||||||
if type(it.dest) != str {
|
|
||||||
it
|
|
||||||
} else {
|
|
||||||
text(fill: accent-color, underline(it.body))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
#import "@preview/codly:1.3.0": *
|
|
||||||
#import "@preview/codly-languages:0.1.10": codly-languages
|
|
||||||
#import "theme.typ": *
|
|
||||||
|
|
||||||
#let codly-init-rule = codly-init.with()
|
|
||||||
|
|
||||||
#let codly-config = codly(
|
|
||||||
languages: codly-languages,
|
|
||||||
fill: code-block-fill,
|
|
||||||
radius: code-block-radius,
|
|
||||||
stroke: none,
|
|
||||||
zebra-fill: none,
|
|
||||||
number-format: none,
|
|
||||||
display-icon: false,
|
|
||||||
display-name: true,
|
|
||||||
default-color: color-body,
|
|
||||||
lang-stroke: (_) => none,
|
|
||||||
lang-fill: (_) => code-block-fill,
|
|
||||||
lang-radius: code-block-radius,
|
|
||||||
)
|
|
||||||
|
|
||||||
#let code-token-highlight-init(doc) = {
|
|
||||||
show raw.where(block: true): set text(fill: color-body)
|
|
||||||
doc
|
|
||||||
}
|
|
||||||
@ -1,265 +0,0 @@
|
|||||||
#import "theme.typ": *
|
|
||||||
|
|
||||||
#let format-cover-date(date, fallback) = {
|
|
||||||
if date != none {
|
|
||||||
date.display("[year].[month repr:numerical].[day]")
|
|
||||||
} else if type(fallback) == str {
|
|
||||||
fallback
|
|
||||||
} else {
|
|
||||||
str(fallback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#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 m = trimmed.match(regex(marker))
|
|
||||||
if m == none {
|
|
||||||
(trimmed, none)
|
|
||||||
} else {
|
|
||||||
let end = m.end
|
|
||||||
let line-2 = trimmed.slice(end)
|
|
||||||
if line-2.len() > 0 {
|
|
||||||
(trimmed.slice(0, end), line-2)
|
|
||||||
} else {
|
|
||||||
(trimmed, none)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#let cover-title-block(line-1, line-2) = {
|
|
||||||
block(breakable: false, spacing: 0pt)[
|
|
||||||
#text(
|
|
||||||
font: heading-font,
|
|
||||||
size: size-cover-title,
|
|
||||||
weight: "bold",
|
|
||||||
fill: cover-panel-title-color,
|
|
||||||
hyphenate: false,
|
|
||||||
top-edge: "cap-height",
|
|
||||||
bottom-edge: "baseline",
|
|
||||||
)[#line-1]
|
|
||||||
#if line-2 != none [
|
|
||||||
#move(dy: cover-panel-title-pull)[
|
|
||||||
#text(
|
|
||||||
font: heading-font,
|
|
||||||
size: size-cover-title-line2,
|
|
||||||
weight: "bold",
|
|
||||||
fill: cover-panel-title-color,
|
|
||||||
hyphenate: false,
|
|
||||||
top-edge: "cap-height",
|
|
||||||
bottom-edge: "baseline",
|
|
||||||
)[#line-2]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
#let cover-logo() = {
|
|
||||||
let mark = cover-logo-size * 0.64
|
|
||||||
let offset = cover-logo-size * 0.36
|
|
||||||
box(width: cover-logo-size, height: cover-logo-size)[
|
|
||||||
#place(left + top)[
|
|
||||||
#rect(width: mark, height: mark, fill: color-primary)
|
|
||||||
]
|
|
||||||
#place(left + top, dx: offset, dy: offset)[
|
|
||||||
#rect(width: mark, height: mark, fill: none, stroke: 1.5pt + color-primary)
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
#let cover-quote-mark() = {
|
|
||||||
text(
|
|
||||||
font: heading-font,
|
|
||||||
size: cover-quote-size,
|
|
||||||
fill: cover-quote-color,
|
|
||||||
)[”]
|
|
||||||
}
|
|
||||||
|
|
||||||
#let cover-panel-footer(meta, date-text) = {
|
|
||||||
block(width: 100%, breakable: false)[
|
|
||||||
#text(font: heading-font, size: cover-panel-author-size, weight: "bold", fill: cover-panel-title-color)[
|
|
||||||
#meta.company
|
|
||||||
]
|
|
||||||
#v(cover-panel-text-gap * 0.25)
|
|
||||||
#text(font: body-font, size: cover-panel-role-size, fill: cover-panel-subtitle-color)[
|
|
||||||
技术报告 · #meta.version
|
|
||||||
]
|
|
||||||
#v(cover-panel-role-gap-before-line)
|
|
||||||
#block(width: 100%, breakable: false)[
|
|
||||||
#place(right + top)[
|
|
||||||
#cover-quote-mark()
|
|
||||||
]
|
|
||||||
#block(width: 100%, inset: (right: cover-quote-clearance))[
|
|
||||||
#line(length: cover-panel-footer-line-length, stroke: cover-panel-footer-rule-stroke + cover-panel-footer-line-color)
|
|
||||||
#v(cover-panel-meta-gap-after-line)
|
|
||||||
#grid(
|
|
||||||
columns: (auto, auto, auto),
|
|
||||||
column-gutter: cover-panel-meta-column-gap,
|
|
||||||
align: (left, center + horizon, left),
|
|
||||||
[
|
|
||||||
#text(font: body-font, size: cover-panel-meta-label, fill: cover-panel-meta-color)[
|
|
||||||
报告版本
|
|
||||||
]
|
|
||||||
#v(tw(0.5))
|
|
||||||
#text(font: body-font, size: cover-panel-meta-size, fill: cover-panel-title-color)[
|
|
||||||
#meta.version
|
|
||||||
]
|
|
||||||
],
|
|
||||||
box(width: cover-panel-meta-divider-width, height: tw(8), fill: cover-panel-footer-line-color),
|
|
||||||
[
|
|
||||||
#text(font: body-font, size: cover-panel-meta-label, fill: cover-panel-meta-color)[
|
|
||||||
发布日期
|
|
||||||
]
|
|
||||||
#v(tw(0.5))
|
|
||||||
#text(font: body-font, size: cover-panel-meta-size, fill: cover-panel-title-color)[
|
|
||||||
#date-text
|
|
||||||
]
|
|
||||||
],
|
|
||||||
)
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
#let cover-panel-bottom(meta, date-text) = {
|
|
||||||
cover-panel-footer(meta, date-text)
|
|
||||||
}
|
|
||||||
|
|
||||||
#let cover-below-panel(meta, date-text) = {
|
|
||||||
block(height: cover-band-height)[
|
|
||||||
#pad(left: cover-footer-inset)[
|
|
||||||
#align(horizon)[
|
|
||||||
#grid(
|
|
||||||
columns: (auto, auto, auto),
|
|
||||||
column-gutter: cover-footer-column-gap,
|
|
||||||
align: bottom,
|
|
||||||
[
|
|
||||||
#text(font: heading-font, size: cover-footer-label, weight: "bold", fill: cover-footer-heading)[
|
|
||||||
单位
|
|
||||||
]
|
|
||||||
#v(cover-footer-line-gap)
|
|
||||||
#text(font: body-font, size: cover-footer-body, fill: cover-footer-text)[
|
|
||||||
#meta.company
|
|
||||||
]
|
|
||||||
#v(cover-footer-line-gap-tight)
|
|
||||||
#text(font: body-font, size: cover-footer-note, fill: cover-text-muted)[
|
|
||||||
智能矿石分选 · 技术方案与工程实施
|
|
||||||
]
|
|
||||||
],
|
|
||||||
box(width: 1pt, height: cover-footer-divider-height, fill: cover-footer-rule),
|
|
||||||
[
|
|
||||||
#text(font: heading-font, size: cover-footer-label, weight: "bold", fill: cover-footer-heading)[
|
|
||||||
信息
|
|
||||||
]
|
|
||||||
#v(cover-footer-line-gap)
|
|
||||||
#text(font: body-font, size: cover-footer-body, fill: cover-footer-text)[
|
|
||||||
文档类型 技术报告
|
|
||||||
]
|
|
||||||
#v(cover-footer-line-gap-tight)
|
|
||||||
#text(font: body-font, size: cover-footer-note, fill: cover-text-muted)[
|
|
||||||
#meta.brand · #meta.version · #date-text
|
|
||||||
]
|
|
||||||
],
|
|
||||||
)
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
#let cover-page(meta, date: none) = {
|
|
||||||
let date-text = format-cover-date(date, meta.date)
|
|
||||||
let (title-line-1, title-line-2) = cover-title-lines(meta.title)
|
|
||||||
|
|
||||||
page(
|
|
||||||
paper: "a4",
|
|
||||||
margin: page-margin-cover,
|
|
||||||
fill: cover-bg,
|
|
||||||
header: none,
|
|
||||||
footer: none,
|
|
||||||
)[
|
|
||||||
#block(width: 100%, height: cover-body-height)[
|
|
||||||
#block(height: cover-band-height)[
|
|
||||||
#pad(left: cover-content-inset)[
|
|
||||||
#align(horizon)[
|
|
||||||
#grid(
|
|
||||||
columns: (auto, 1fr),
|
|
||||||
column-gutter: tw(3),
|
|
||||||
align: horizon,
|
|
||||||
cover-logo(),
|
|
||||||
[
|
|
||||||
#text(font: heading-font, size: cover-brand-size, weight: "bold", fill: cover-text)[
|
|
||||||
#meta.brand
|
|
||||||
]
|
|
||||||
#v(cover-footer-line-gap)
|
|
||||||
#text(font: body-font, size: cover-tagline-size, fill: cover-text-muted)[
|
|
||||||
#meta.company
|
|
||||||
]
|
|
||||||
],
|
|
||||||
)
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
#v(cover-header-gap)
|
|
||||||
|
|
||||||
#pad(right: cover-panel-right-gap)[
|
|
||||||
#block(width: 100%, height: cover-panel-height, fill: cover-panel-fill)[
|
|
||||||
#pad(
|
|
||||||
left: cover-content-inset,
|
|
||||||
right: cover-margin-right,
|
|
||||||
top: cover-panel-inset-y,
|
|
||||||
bottom: cover-panel-inset-bottom-y,
|
|
||||||
)[
|
|
||||||
#block(width: 100%, height: 100%)[
|
|
||||||
#place(top + left)[
|
|
||||||
#block(width: 100%)[
|
|
||||||
#text(
|
|
||||||
font: heading-font,
|
|
||||||
size: cover-panel-kicker,
|
|
||||||
weight: "medium",
|
|
||||||
fill: cover-panel-kicker-color,
|
|
||||||
tracking: 0.08em,
|
|
||||||
)[TECHNICAL REPORT · 技术报告]
|
|
||||||
|
|
||||||
#v(cover-panel-title-outer-gap)
|
|
||||||
#cover-title-block(title-line-1, title-line-2)
|
|
||||||
|
|
||||||
#v(cover-panel-title-outer-gap)
|
|
||||||
#text(
|
|
||||||
font: heading-font,
|
|
||||||
size: size-cover-subtitle,
|
|
||||||
fill: cover-panel-subtitle-color,
|
|
||||||
tracking: 0.04em,
|
|
||||||
)[INTELLIGENT ORE SORTING · 智能矿石分选]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
#place(left + horizon)[
|
|
||||||
#line(
|
|
||||||
length: cover-panel-rule-width,
|
|
||||||
stroke: cover-panel-accent-stroke + cover-panel-divider-color,
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
#place(bottom + left)[
|
|
||||||
#block(width: 100%, breakable: false)[
|
|
||||||
#cover-panel-bottom(meta, date-text)
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
#v(cover-below-gap)
|
|
||||||
#cover-below-panel(meta, date-text)
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
// Tailwind CSS v3 默认刻度(1rem = 12pt,用于 Typst 印刷排版)
|
|
||||||
#let tw-rem = 12pt
|
|
||||||
|
|
||||||
// spacing:scale × 0.25rem(等同 Tailwind p-*, m-*, gap-*)
|
|
||||||
#let tw(scale) = scale * 0.25 * tw-rem
|
|
||||||
|
|
||||||
// font-size(等同 Tailwind text-*)
|
|
||||||
#let text-xs = 0.75 * tw-rem
|
|
||||||
#let text-sm = 0.875 * tw-rem
|
|
||||||
#let text-base = 1 * tw-rem
|
|
||||||
#let text-lg = 1.125 * tw-rem
|
|
||||||
#let text-xl = 1.25 * tw-rem
|
|
||||||
#let text-2xl = 1.5 * tw-rem
|
|
||||||
#let text-3xl = 1.875 * tw-rem
|
|
||||||
#let text-4xl = 2.25 * tw-rem
|
|
||||||
#let text-5xl = 3 * tw-rem
|
|
||||||
#let text-6xl = 3.75 * tw-rem
|
|
||||||
#let text-7xl = 4.5 * tw-rem
|
|
||||||
#let text-8xl = 6 * tw-rem
|
|
||||||
#let text-9xl = 8 * tw-rem
|
|
||||||
|
|
||||||
// line-height(等同 Tailwind leading-*,值为倍数)
|
|
||||||
#let leading-none = 1
|
|
||||||
#let leading-tight = 1.25
|
|
||||||
#let leading-snug = 1.375
|
|
||||||
#let leading-normal = 1.5
|
|
||||||
#let leading-relaxed = 1.625
|
|
||||||
#let leading-loose = 2
|
|
||||||
@ -1,141 +0,0 @@
|
|||||||
#import "../../brand/colors.typ": *
|
|
||||||
#import "tailwind.typ": *
|
|
||||||
|
|
||||||
// 技术报告 · 主色 #3052c8
|
|
||||||
#let color-primary = rgb("#3052c8")
|
|
||||||
#let color-accent-surface = color-primary.lighten(88%)
|
|
||||||
#let color-body-text = color-body
|
|
||||||
#let color-caption = rgb(110, 110, 110)
|
|
||||||
#let quote-bar-stroke = 2.5pt
|
|
||||||
#let quote-bar-color = rgb("#f6f7f8")
|
|
||||||
#let color-block-bg = rgb("#f6f7f8")
|
|
||||||
|
|
||||||
// 字体:微软雅黑
|
|
||||||
#let report-font = ("Microsoft YaHei", "Microsoft YaHei UI")
|
|
||||||
#let heading-font = report-font
|
|
||||||
#let body-font = report-font
|
|
||||||
#let mono-font = report-font
|
|
||||||
|
|
||||||
// 正文(text-base · leading-normal)
|
|
||||||
#let size-body = text-base
|
|
||||||
#let leading-ratio = leading-normal
|
|
||||||
#let size-caption = text-sm
|
|
||||||
|
|
||||||
#let space-micro = tw(1)
|
|
||||||
#let space-chapter = tw(12)
|
|
||||||
|
|
||||||
#let image-max-width = 100%
|
|
||||||
|
|
||||||
#let code-block-fill = color-block-bg
|
|
||||||
#let code-block-radius = tw(1.5)
|
|
||||||
#let code-inline-radius = tw(0.75)
|
|
||||||
|
|
||||||
// --- 页面边距 ---
|
|
||||||
#let page-margin-a4 = 2.5cm
|
|
||||||
#let page-margin-x = 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-right = tw(8)
|
|
||||||
#let cover-content-inset = tw(11)
|
|
||||||
#let cover-footer-inset = cover-content-inset
|
|
||||||
#let cover-band-height = tw(24)
|
|
||||||
#let cover-header-est = cover-band-height
|
|
||||||
#let cover-footer-est = cover-band-height
|
|
||||||
#let cover-footer-line-gap-tight = tw(0.5)
|
|
||||||
#let cover-footer-line-gap = tw(0.75)
|
|
||||||
#let cover-footer-column-gap = tw(16)
|
|
||||||
#let cover-panel-right-gap = tw(24)
|
|
||||||
#let page-margin-cover = (
|
|
||||||
top: cover-margin-y,
|
|
||||||
bottom: cover-margin-y,
|
|
||||||
left: 0pt,
|
|
||||||
right: cover-margin-right,
|
|
||||||
)
|
|
||||||
|
|
||||||
// --- 封面(Proposal 色块布局 · 蓝色系)---
|
|
||||||
#let cover-bg = white
|
|
||||||
#let cover-text = color-ink
|
|
||||||
#let cover-text-muted = color-muted
|
|
||||||
#let cover-logo-size = tw(10)
|
|
||||||
#let cover-brand-size = text-base
|
|
||||||
#let cover-tagline-size = text-sm
|
|
||||||
#let cover-body-height = 25.7cm
|
|
||||||
#let cover-panel-gap-y = tw(6)
|
|
||||||
#let cover-header-gap = cover-panel-gap-y + cover-footer-est - cover-header-est
|
|
||||||
#let cover-below-gap = cover-panel-gap-y
|
|
||||||
#let cover-panel-fill = color-primary
|
|
||||||
#let cover-panel-height = cover-body-height - cover-header-est - cover-footer-est - cover-header-gap - cover-below-gap
|
|
||||||
#let cover-panel-inset-y = tw(18)
|
|
||||||
#let cover-panel-inset-bottom-y = tw(16)
|
|
||||||
#let cover-panel-text-gap = tw(4)
|
|
||||||
#let cover-panel-title-outer-gap = tw(5)
|
|
||||||
#let cover-panel-title-pull = -tw(8)
|
|
||||||
#let cover-quote-column-width = tw(40)
|
|
||||||
#let cover-panel-footer-rule-stroke = 2pt
|
|
||||||
#let cover-panel-meta-divider-width = 2pt
|
|
||||||
#let cover-panel-kicker = text-sm
|
|
||||||
#let cover-panel-kicker-color = white.transparentize(18%)
|
|
||||||
#let cover-panel-title-color = white
|
|
||||||
#let cover-panel-subtitle-color = white.transparentize(12%)
|
|
||||||
#let cover-panel-divider-color = white
|
|
||||||
#let cover-panel-accent-stroke = 3.5pt
|
|
||||||
#let cover-panel-line-color = white.transparentize(45%)
|
|
||||||
#let cover-panel-footer-line-color = white.transparentize(15%)
|
|
||||||
#let cover-panel-rule-width = tw(22)
|
|
||||||
#let cover-panel-meta-column-gap = tw(8)
|
|
||||||
#let cover-panel-author-size = text-base
|
|
||||||
#let cover-panel-role-size = text-sm
|
|
||||||
#let cover-panel-meta-size = text-sm
|
|
||||||
#let cover-panel-meta-label = text-xs
|
|
||||||
#let cover-panel-meta-color = white.transparentize(12%)
|
|
||||||
#let cover-quote-size = 16 * tw-rem
|
|
||||||
#let cover-quote-color = white.transparentize(8%)
|
|
||||||
#let cover-quote-clearance = cover-quote-column-width
|
|
||||||
#let cover-quote-offset-y = tw(0)
|
|
||||||
#let cover-panel-role-gap-before-line = tw(4)
|
|
||||||
#let cover-panel-meta-gap-after-line = tw(3)
|
|
||||||
#let cover-panel-footer-line-length = 78%
|
|
||||||
#let cover-footer-divider-height = tw(7.5)
|
|
||||||
#let cover-footer-label = text-sm
|
|
||||||
#let cover-footer-body = text-sm
|
|
||||||
#let cover-footer-note = text-xs
|
|
||||||
#let cover-footer-heading = color-ink
|
|
||||||
#let cover-footer-text = color-body
|
|
||||||
#let cover-footer-rule = color-muted.transparentize(55%)
|
|
||||||
#let size-cover-title = text-6xl
|
|
||||||
#let size-cover-title-line2 = text-7xl
|
|
||||||
#let size-cover-subtitle = text-lg
|
|
||||||
|
|
||||||
// --- 目录页 ---
|
|
||||||
#let toc-head-gap = tw(18)
|
|
||||||
#let toc-content-indent = tw(12)
|
|
||||||
#let summary-top-offset = tw(10)
|
|
||||||
#let summary-body-gap = tw(8)
|
|
||||||
#let toc-head-zh = text-5xl
|
|
||||||
#let toc-l2-color = color-muted.lighten(28%)
|
|
||||||
#let toc-head-color = color-primary
|
|
||||||
#let toc-classification-label = "C3 Confidential"
|
|
||||||
#let toc-classification-size = text-xs
|
|
||||||
#let toc-classification-color = toc-l2-color
|
|
||||||
#let toc-classification-dx = -page-margin-x + tw(3)
|
|
||||||
#let toc-classification-dy = page-margin-y - tw(7)
|
|
||||||
#let toc-l1-number-width = tw(14)
|
|
||||||
#let toc-l1-number-title-gap = tw(11)
|
|
||||||
#let toc-l1-number-size = text-5xl
|
|
||||||
#let toc-l1-number-color = color-primary
|
|
||||||
#let toc-l1-size = text-lg
|
|
||||||
#let toc-l2-size = text-sm
|
|
||||||
#let toc-page-size = text-sm
|
|
||||||
#let toc-l1-color = color-primary
|
|
||||||
#let toc-l1-leader-color = color-primary.lighten(22%)
|
|
||||||
#let toc-l2-leader-color = toc-l2-color.transparentize(35%)
|
|
||||||
#let toc-leader-dot-size = text-xs
|
|
||||||
#let toc-leader-gap = tw(0.5)
|
|
||||||
#let toc-l1-gap-above = tw(6)
|
|
||||||
#let toc-l1-gap-below = tw(2.5)
|
|
||||||
#let toc-l2-gap-above = tw(2.5)
|
|
||||||
#let toc-l2-gap-below = tw(2)
|
|
||||||
@ -1,137 +0,0 @@
|
|||||||
#import "theme.typ": *
|
|
||||||
|
|
||||||
#let toc-unnumbered-bodies = ([摘要],)
|
|
||||||
|
|
||||||
#let toc-register-chapter-counter() = doc => {
|
|
||||||
show heading.where(level: 1): it => {
|
|
||||||
if not toc-unnumbered-bodies.contains(it.body) {
|
|
||||||
counter("toc-chapter").step()
|
|
||||||
}
|
|
||||||
it
|
|
||||||
}
|
|
||||||
doc
|
|
||||||
}
|
|
||||||
|
|
||||||
#let toc-leader(leader-color) = {
|
|
||||||
box(
|
|
||||||
width: 1fr,
|
|
||||||
height: 0.9em,
|
|
||||||
clip: true,
|
|
||||||
align(horizon + left)[
|
|
||||||
#repeat[#text(size: toc-leader-dot-size, fill: leader-color)[·#h(toc-leader-gap)]]
|
|
||||||
],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#let toc-format-num(n) = {
|
|
||||||
if n < 10 {
|
|
||||||
"0" + str(n)
|
|
||||||
} else {
|
|
||||||
str(n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#let toc-l1-chapter-num(entry) = {
|
|
||||||
toc-format-num(counter("toc-chapter").at(entry.element.location()).first())
|
|
||||||
}
|
|
||||||
|
|
||||||
#let toc-number-cell(skip-number, entry) = {
|
|
||||||
box(width: toc-l1-number-width)[
|
|
||||||
#align(left)[
|
|
||||||
#if not skip-number [
|
|
||||||
#text(
|
|
||||||
font: heading-font,
|
|
||||||
size: toc-l1-number-size,
|
|
||||||
weight: "bold",
|
|
||||||
fill: toc-l1-number-color,
|
|
||||||
)[#toc-l1-chapter-num(entry)]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
#let toc-entry-show(it) = {
|
|
||||||
if it.level == 1 and toc-unnumbered-bodies.contains(it.body()) {
|
|
||||||
[]
|
|
||||||
} else if it.level == 1 {
|
|
||||||
let skip-number = toc-unnumbered-bodies.contains(it.body())
|
|
||||||
block(width: 100%, above: toc-l1-gap-above, below: toc-l1-gap-below)[
|
|
||||||
#grid(
|
|
||||||
columns: (toc-l1-number-width, toc-l1-number-title-gap, auto, 1fr, auto),
|
|
||||||
column-gutter: tw(2),
|
|
||||||
align: (left + horizon, left, left + horizon, horizon, horizon),
|
|
||||||
toc-number-cell(skip-number, it),
|
|
||||||
[],
|
|
||||||
text(font: heading-font, size: toc-l1-size, weight: "bold", fill: toc-l1-color)[
|
|
||||||
#it.body()
|
|
||||||
],
|
|
||||||
toc-leader(toc-l1-leader-color),
|
|
||||||
text(font: heading-font, size: toc-page-size, weight: "bold", fill: toc-l1-color)[
|
|
||||||
#it.page()
|
|
||||||
],
|
|
||||||
)
|
|
||||||
]
|
|
||||||
} else if it.level == 2 {
|
|
||||||
block(width: 100%, above: toc-l2-gap-above, below: toc-l2-gap-below)[
|
|
||||||
#grid(
|
|
||||||
columns: (toc-l1-number-width, toc-l1-number-title-gap, auto, 1fr, auto),
|
|
||||||
column-gutter: tw(2),
|
|
||||||
align: horizon,
|
|
||||||
[],
|
|
||||||
[],
|
|
||||||
text(font: body-font, size: toc-l2-size, weight: "regular", fill: toc-l2-color)[
|
|
||||||
#it.body()
|
|
||||||
],
|
|
||||||
toc-leader(toc-l2-leader-color),
|
|
||||||
text(font: body-font, size: toc-page-size, fill: toc-l2-color)[#it.page()],
|
|
||||||
)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#let toc-classification-mark() = {
|
|
||||||
place(left + bottom, dx: toc-classification-dx, dy: toc-classification-dy)[
|
|
||||||
#text(
|
|
||||||
font: body-font,
|
|
||||||
size: toc-classification-size,
|
|
||||||
fill: toc-classification-color,
|
|
||||||
tracking: 0.04em,
|
|
||||||
)[
|
|
||||||
#rotate(-90deg, reflow: true)[#toc-classification-label]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
#let toc-page(meta) = {
|
|
||||||
let _ = meta
|
|
||||||
pagebreak(weak: true)
|
|
||||||
|
|
||||||
page(
|
|
||||||
header: none,
|
|
||||||
footer: none,
|
|
||||||
margin: (
|
|
||||||
top: page-margin-y,
|
|
||||||
bottom: page-margin-y,
|
|
||||||
left: page-margin-x,
|
|
||||||
right: page-margin-x,
|
|
||||||
),
|
|
||||||
)[
|
|
||||||
#block(width: 100%, height: 100%)[
|
|
||||||
#toc-classification-mark()
|
|
||||||
#block(width: 100%, below: space-chapter)[
|
|
||||||
#text(font: heading-font, size: toc-head-zh, weight: "bold", fill: toc-head-color)[
|
|
||||||
报告目录
|
|
||||||
]
|
|
||||||
|
|
||||||
#v(toc-head-gap)
|
|
||||||
|
|
||||||
#pad(left: toc-content-indent)[
|
|
||||||
#show outline.entry: toc-entry-show
|
|
||||||
#outline(depth: 2, indent: 0pt, title: none)
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
pagebreak(weak: true)
|
|
||||||
}
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
#import "data/config.typ": *
|
|
||||||
#import "data/theme.typ": *
|
|
||||||
#import "data/cover.typ": cover-page
|
|
||||||
#import "data/toc.typ": toc-page, toc-register-chapter-counter
|
|
||||||
#import "data/body.typ": report-body, start-body-page-numbering
|
|
||||||
#import "data/diagrams.typ": ore-sorting-flow
|
|
||||||
#import "data/code.typ": codly-init-rule, codly-config, code-token-highlight-init
|
|
||||||
#import "data/md.typ": load-report-md, parse-report-date
|
|
||||||
|
|
||||||
#show: codly-init-rule
|
|
||||||
#show: code-token-highlight-init
|
|
||||||
#codly-config
|
|
||||||
|
|
||||||
#let report = load-report-md(
|
|
||||||
read(content-path),
|
|
||||||
source-path: content-path,
|
|
||||||
extra-scope: (
|
|
||||||
ore-sorting-flow: ore-sorting-flow,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
#let meta = report.metadata
|
|
||||||
#let report-date = parse-report-date(meta.date)
|
|
||||||
|
|
||||||
#cover-page(meta, date: report-date)
|
|
||||||
|
|
||||||
#show: report-body.with(
|
|
||||||
title: meta.title,
|
|
||||||
author: meta.brand,
|
|
||||||
date: report-date,
|
|
||||||
body-font: body-font,
|
|
||||||
heading-font: heading-font,
|
|
||||||
raw-font: mono-font,
|
|
||||||
font-size: size-body,
|
|
||||||
leading-ratio: leading-ratio,
|
|
||||||
margin-x: body-margin-x,
|
|
||||||
margin-y: body-margin-y,
|
|
||||||
)
|
|
||||||
|
|
||||||
#set heading(numbering: "1.1.1.1")
|
|
||||||
#show: toc-register-chapter-counter()
|
|
||||||
|
|
||||||
#toc-page(meta)
|
|
||||||
|
|
||||||
#if meta.summary != "" [
|
|
||||||
#v(summary-top-offset, weak: false)
|
|
||||||
#meta.summary
|
|
||||||
#v(summary-body-gap)
|
|
||||||
]
|
|
||||||
|
|
||||||
#start-body-page-numbering()
|
|
||||||
|
|
||||||
#report.body
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,56 +0,0 @@
|
|||||||
# Travel Plan · 旅行计划
|
|
||||||
|
|
||||||
存放行程参考图、链接与笔记;后续可导出为 Typst/PDF 时间轴版式(见截图参考)。
|
|
||||||
|
|
||||||
## 目录结构
|
|
||||||
|
|
||||||
```
|
|
||||||
travel-plan/
|
|
||||||
├── plan.typ # 入口(排版占位,待完善)
|
|
||||||
├── data/
|
|
||||||
│ ├── config.typ # 行程结构(天 / 时段 / 地点)
|
|
||||||
│ └── theme.typ # 样式 token
|
|
||||||
├── trips/ # ★ 每次旅行一个子文件夹
|
|
||||||
│ └── <trip-name>/
|
|
||||||
│ ├── links.md # 参考链接(地图、攻略、订房等)
|
|
||||||
│ ├── notes.md # 可选:文字备忘
|
|
||||||
│ └── refs/ # 参考图,按地点分子目录
|
|
||||||
│ ├── donggang/
|
|
||||||
│ ├── xiaogang/
|
|
||||||
│ └── ...
|
|
||||||
└── local/ # 个人行程(gitignore,不提交)
|
|
||||||
```
|
|
||||||
|
|
||||||
| 放什么 | 路径 | 说明 |
|
|
||||||
|--------|------|------|
|
|
||||||
| 参考链接 | `trips/<名>/links.md` | Markdown 链接列表,按天或地点分组 |
|
|
||||||
| 参考图 | `trips/<名>/refs/<地点>/` | 文件名建议 `01-简短说明.jpg` |
|
|
||||||
| 文字备忘 | `trips/<名>/notes.md` | 穿搭、机位、tips |
|
|
||||||
| 个人私密行程 | `local/<名>/` | 整目录不提交 Git |
|
|
||||||
|
|
||||||
## 新建一次旅行
|
|
||||||
|
|
||||||
1. 复制 `trips/_example/` 为 `trips/dalian-2026/`(名字自定)
|
|
||||||
2. 在 `refs/` 下按地点建文件夹,把参考图丢进去
|
|
||||||
3. 在 `links.md` 里补地图、小红书、订房链接等
|
|
||||||
4. 需要出 PDF 时再改 `data/config.typ` 并编译 `plan.typ`
|
|
||||||
|
|
||||||
## 参考图命名建议
|
|
||||||
|
|
||||||
```
|
|
||||||
refs/xiaogang/
|
|
||||||
├── 01-亲海栈道主视觉.jpg
|
|
||||||
├── 02-慢走背影感.jpg
|
|
||||||
└── 03-双人构图参考.jpg
|
|
||||||
```
|
|
||||||
|
|
||||||
## 编译(占位)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
typst compile --root . travel-plan/plan.typ travel-plan/sample.pdf
|
|
||||||
```
|
|
||||||
|
|
||||||
## 版式参考
|
|
||||||
|
|
||||||
- **日程页**:D1 标题 + 摘要 + 左侧时间轴 + 卡片(时段 / 活动 / tips)
|
|
||||||
- **地点页**:地点标题 + 时段 + 说明 + 参考图网格(带 caption)
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
// 指向 trips/ 下某次旅行;排版完善后从 refs/ 读取参考图
|
|
||||||
#let trip-id = "_example"
|
|
||||||
|
|
||||||
#let trip = (
|
|
||||||
title: "大连 · 示例行程",
|
|
||||||
subtitle: "落地放行李,中午就开始玩",
|
|
||||||
)
|
|
||||||
|
|
||||||
#let days = (
|
|
||||||
(
|
|
||||||
id: "D1",
|
|
||||||
title: "西安飞大连 · 东港 / 小岗开场",
|
|
||||||
summary: "第一天主打东港、亲海栈道、蓝调海边和夜景。",
|
|
||||||
stops: (
|
|
||||||
(
|
|
||||||
time: "06:40–08:55",
|
|
||||||
title: "西安飞大连",
|
|
||||||
note: "可在飞机上化妆,落地后酒店再补状态。",
|
|
||||||
active: true,
|
|
||||||
),
|
|
||||||
(
|
|
||||||
time: "10:00–12:00",
|
|
||||||
title: "酒店放行李 + 收拾状态",
|
|
||||||
note: "建议住中山区 / 东港附近,晚上动线更顺。",
|
|
||||||
active: false,
|
|
||||||
),
|
|
||||||
(
|
|
||||||
time: "14:00–16:30",
|
|
||||||
title: "东港商务区",
|
|
||||||
note: "先拍现代建筑和海边步道,建立「大连城市感」。",
|
|
||||||
active: false,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
#import "/brand/colors.typ": *
|
|
||||||
|
|
||||||
#let color-primary = color-brand
|
|
||||||
#let color-heading = color-ink
|
|
||||||
#let color-text = color-body
|
|
||||||
#let color-text-light = color-muted
|
|
||||||
#let color-meta = rgb("#9ca3af")
|
|
||||||
#let color-card-border = rgb("#e5e7eb")
|
|
||||||
#let color-timeline = rgb("#d1d5db")
|
|
||||||
|
|
||||||
#let body-font = ("Segoe UI", "Microsoft YaHei UI", "Microsoft YaHei")
|
|
||||||
#let heading-font = body-font
|
|
||||||
#let mono-font = ("Consolas", "Cascadia Mono")
|
|
||||||
|
|
||||||
#let size-label = 8pt
|
|
||||||
#let size-day = 22pt
|
|
||||||
#let size-title = 16pt
|
|
||||||
#let size-body = 10.5pt
|
|
||||||
#let size-time = 9pt
|
|
||||||
#let size-caption = 8.5pt
|
|
||||||
|
|
||||||
#let leading-body = size-body * 1.45
|
|
||||||
#let space-section = 18pt
|
|
||||||
#let space-card = 10pt
|
|
||||||
#let card-radius = 6pt
|
|
||||||
#let card-inset = 12pt
|
|
||||||
|
|
||||||
#let page-margin = (
|
|
||||||
top: 1.8cm,
|
|
||||||
bottom: 1.8cm,
|
|
||||||
left: 2cm,
|
|
||||||
right: 2cm,
|
|
||||||
)
|
|
||||||
@ -1,101 +0,0 @@
|
|||||||
#import "data/config.typ": *
|
|
||||||
#import "data/theme.typ": *
|
|
||||||
|
|
||||||
#set page(paper: "a4", margin: page-margin, fill: white)
|
|
||||||
#set text(font: body-font, size: size-body, fill: color-text, lang: "zh")
|
|
||||||
#set par(leading: leading-body, spacing: 0pt, justify: false)
|
|
||||||
|
|
||||||
#let schedule-label() = {
|
|
||||||
text(font: mono-font, size: size-label, fill: color-meta, tracking: 0.08em)[DETAILED SCHEDULE]
|
|
||||||
}
|
|
||||||
|
|
||||||
#let day-badge(id) = {
|
|
||||||
box(
|
|
||||||
width: 1.35em,
|
|
||||||
height: 1.35em,
|
|
||||||
radius: 50%,
|
|
||||||
fill: color-heading,
|
|
||||||
inset: 0pt,
|
|
||||||
)[
|
|
||||||
#align(center + horizon)[
|
|
||||||
#text(font: heading-font, size: 11pt, weight: "bold", fill: white)[#id]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
#let timeline-dot(active: false) = {
|
|
||||||
box(
|
|
||||||
width: if active { 8pt } else { 6pt },
|
|
||||||
height: if active { 8pt } else { 6pt },
|
|
||||||
radius: 50%,
|
|
||||||
fill: if active { color-heading } else { color-timeline },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#let stop-card(stop) = {
|
|
||||||
box(
|
|
||||||
width: 100%,
|
|
||||||
stroke: 0.6pt + color-card-border,
|
|
||||||
radius: card-radius,
|
|
||||||
inset: card-inset,
|
|
||||||
)[
|
|
||||||
#text(font: mono-font, size: size-time, fill: color-meta)[#stop.time]
|
|
||||||
#v(0.35em)
|
|
||||||
#text(font: heading-font, size: size-title, weight: "bold", fill: color-heading)[#stop.title]
|
|
||||||
#if stop.note != "" [
|
|
||||||
#v(0.45em)
|
|
||||||
#text(fill: color-text-light)[#stop.note]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
#let day-section(day) = block(breakable: true, below: space-section)[
|
|
||||||
#schedule-label()
|
|
||||||
#v(0.6em)
|
|
||||||
#grid(
|
|
||||||
columns: (auto, 1fr),
|
|
||||||
column-gutter: 0.55em,
|
|
||||||
align: horizon,
|
|
||||||
day-badge(day.id),
|
|
||||||
text(font: heading-font, size: size-day, weight: "bold", fill: color-heading)[#day.title],
|
|
||||||
)
|
|
||||||
#v(0.45em)
|
|
||||||
#text(fill: color-text-light)[#day.summary]
|
|
||||||
#v(0.9em)
|
|
||||||
#for (i, stop) in day.stops.enumerate() [
|
|
||||||
#grid(
|
|
||||||
columns: (16pt, 1fr),
|
|
||||||
column-gutter: 10pt,
|
|
||||||
align: (center, top),
|
|
||||||
box(width: 16pt)[
|
|
||||||
#align(center)[
|
|
||||||
#timeline-dot(active: stop.active)
|
|
||||||
#if i < day.stops.len() - 1 [
|
|
||||||
#v(-0.2em)
|
|
||||||
#box(width: 1pt, height: 4.2em, fill: color-timeline)
|
|
||||||
]
|
|
||||||
]
|
|
||||||
],
|
|
||||||
stop-card(stop),
|
|
||||||
)
|
|
||||||
#if i < day.stops.len() - 1 [#v(space-card)]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
#align(left)[
|
|
||||||
#text(font: heading-font, size: 20pt, weight: "bold", fill: color-primary)[#trip.title]
|
|
||||||
#v(0.3em)
|
|
||||||
#text(fill: color-text-light)[#trip.subtitle]
|
|
||||||
#v(1.2em)
|
|
||||||
]
|
|
||||||
|
|
||||||
#for day in days [
|
|
||||||
#day-section(day)
|
|
||||||
]
|
|
||||||
|
|
||||||
#v(1em)
|
|
||||||
#align(left)[
|
|
||||||
#text(size: size-caption, fill: color-meta)[
|
|
||||||
参考图与链接见 #raw("trips/" + trip-id + "/") — 排版占位,地点图区待接 refs/
|
|
||||||
]
|
|
||||||
]
|
|
||||||
@ -1,837 +0,0 @@
|
|||||||
%PDF-1.7
|
|
||||||
%€€€€
|
|
||||||
|
|
||||||
1 0 obj
|
|
||||||
<</Type/Pages/Count 1/Kids[67 0 R]>>
|
|
||||||
endobj
|
|
||||||
2 0 obj
|
|
||||||
<</Type/StructTreeRoot/RoleMap<</Datetime/Span/Terms/Part/Title/P/Strong/Span/Em/Span>>/K[33 0 R]/ParentTree<</Nums[0 3 0 R]>>/ParentTreeNextKey 1>>
|
|
||||||
endobj
|
|
||||||
3 0 obj
|
|
||||||
[4 0 R 4 0 R 4 0 R 5 0 R 6 0 R 7 0 R 9 0 R 9 0 R 9 0 R 9 0 R 9 0 R 12 0 R 14 0 R 15 0 R 16 0 R 20 0 R 21 0 R 21 0 R 21 0 R 22 0 R 22 0 R 22 0 R 26 0 R 27 0 R 28 0 R 32 0 R 32 0 R 31 0 R 32 0 R 32 0 R 32 0 R 32 0 R]
|
|
||||||
endobj
|
|
||||||
4 0 obj
|
|
||||||
<</Type/StructElem/S/P/P 33 0 R/K[0 1 2]/Pg 67 0 R>>
|
|
||||||
endobj
|
|
||||||
5 0 obj
|
|
||||||
<</Type/StructElem/S/P/P 33 0 R/K[3]/Pg 67 0 R>>
|
|
||||||
endobj
|
|
||||||
6 0 obj
|
|
||||||
<</Type/StructElem/S/P/P 33 0 R/K[4]/Pg 67 0 R>>
|
|
||||||
endobj
|
|
||||||
7 0 obj
|
|
||||||
<</Type/StructElem/S/P/P 8 0 R/K[5]/Pg 67 0 R>>
|
|
||||||
endobj
|
|
||||||
8 0 obj
|
|
||||||
<</Type/StructElem/S/Div/P 11 0 R/K[7 0 R]>>
|
|
||||||
endobj
|
|
||||||
9 0 obj
|
|
||||||
<</Type/StructElem/S/Span/P 10 0 R/A[<</O/Layout/Placement/Block>>]/K[6 7 8 9 10]/Pg 67 0 R>>
|
|
||||||
endobj
|
|
||||||
10 0 obj
|
|
||||||
<</Type/StructElem/S/Div/P 11 0 R/K[9 0 R]>>
|
|
||||||
endobj
|
|
||||||
11 0 obj
|
|
||||||
<</Type/StructElem/S/Div/P 33 0 R/K[8 0 R 10 0 R]>>
|
|
||||||
endobj
|
|
||||||
12 0 obj
|
|
||||||
<</Type/StructElem/S/P/P 33 0 R/K[11]/Pg 67 0 R>>
|
|
||||||
endobj
|
|
||||||
13 0 obj
|
|
||||||
<</Type/StructElem/S/Div/P 18 0 R/K[]>>
|
|
||||||
endobj
|
|
||||||
14 0 obj
|
|
||||||
<</Type/StructElem/S/P/P 17 0 R/K[12]/Pg 67 0 R>>
|
|
||||||
endobj
|
|
||||||
15 0 obj
|
|
||||||
<</Type/StructElem/S/P/P 17 0 R/K[13]/Pg 67 0 R>>
|
|
||||||
endobj
|
|
||||||
16 0 obj
|
|
||||||
<</Type/StructElem/S/P/P 17 0 R/K[14]/Pg 67 0 R>>
|
|
||||||
endobj
|
|
||||||
17 0 obj
|
|
||||||
<</Type/StructElem/S/Div/P 18 0 R/K[14 0 R 15 0 R 16 0 R]>>
|
|
||||||
endobj
|
|
||||||
18 0 obj
|
|
||||||
<</Type/StructElem/S/Div/P 33 0 R/K[13 0 R 17 0 R]>>
|
|
||||||
endobj
|
|
||||||
19 0 obj
|
|
||||||
<</Type/StructElem/S/Div/P 24 0 R/K[]>>
|
|
||||||
endobj
|
|
||||||
20 0 obj
|
|
||||||
<</Type/StructElem/S/P/P 23 0 R/K[15]/Pg 67 0 R>>
|
|
||||||
endobj
|
|
||||||
21 0 obj
|
|
||||||
<</Type/StructElem/S/P/P 23 0 R/K[16 17 18]/Pg 67 0 R>>
|
|
||||||
endobj
|
|
||||||
22 0 obj
|
|
||||||
<</Type/StructElem/S/P/P 23 0 R/K[19 20 21]/Pg 67 0 R>>
|
|
||||||
endobj
|
|
||||||
23 0 obj
|
|
||||||
<</Type/StructElem/S/Div/P 24 0 R/K[20 0 R 21 0 R 22 0 R]>>
|
|
||||||
endobj
|
|
||||||
24 0 obj
|
|
||||||
<</Type/StructElem/S/Div/P 33 0 R/K[19 0 R 23 0 R]>>
|
|
||||||
endobj
|
|
||||||
25 0 obj
|
|
||||||
<</Type/StructElem/S/Div/P 30 0 R/K[]>>
|
|
||||||
endobj
|
|
||||||
26 0 obj
|
|
||||||
<</Type/StructElem/S/P/P 29 0 R/K[22]/Pg 67 0 R>>
|
|
||||||
endobj
|
|
||||||
27 0 obj
|
|
||||||
<</Type/StructElem/S/P/P 29 0 R/K[23]/Pg 67 0 R>>
|
|
||||||
endobj
|
|
||||||
28 0 obj
|
|
||||||
<</Type/StructElem/S/P/P 29 0 R/K[24]/Pg 67 0 R>>
|
|
||||||
endobj
|
|
||||||
29 0 obj
|
|
||||||
<</Type/StructElem/S/Div/P 30 0 R/K[26 0 R 27 0 R 28 0 R]>>
|
|
||||||
endobj
|
|
||||||
30 0 obj
|
|
||||||
<</Type/StructElem/S/Div/P 33 0 R/K[25 0 R 29 0 R]>>
|
|
||||||
endobj
|
|
||||||
31 0 obj
|
|
||||||
<</Type/StructElem/S/Code/P 32 0 R/Lang(en)/K[27]/Pg 67 0 R>>
|
|
||||||
endobj
|
|
||||||
32 0 obj
|
|
||||||
<</Type/StructElem/S/P/P 33 0 R/K[25 26 31 0 R 28 29 30 31]/Pg 67 0 R>>
|
|
||||||
endobj
|
|
||||||
33 0 obj
|
|
||||||
<</Type/StructElem/S/Document/P 2 0 R/K[4 0 R 5 0 R 6 0 R 11 0 R 12 0 R 18 0 R 24 0 R 30 0 R 32 0 R]>>
|
|
||||||
endobj
|
|
||||||
34 0 obj
|
|
||||||
[/ICCBased 99 0 R]
|
|
||||||
endobj
|
|
||||||
35 0 obj
|
|
||||||
[/ICCBased 100 0 R]
|
|
||||||
endobj
|
|
||||||
36 0 obj
|
|
||||||
<</ProcSet[/PDF/Text/ImageC/ImageB]/ColorSpace<</c0 34 0 R/c1 35 0 R>>/Font<</f0 37 0 R/f1 40 0 R/f2 43 0 R/f3 46 0 R/f4 49 0 R/f5 52 0 R/f6 55 0 R/f7 58 0 R/f8 61 0 R/f9 64 0 R>>>>
|
|
||||||
endobj
|
|
||||||
37 0 obj
|
|
||||||
<</Type/Font/Subtype/Type0/BaseFont/KBDGOZ+MicrosoftYaHeiUI-Bold/Encoding/Identity-H/DescendantFonts[38 0 R]/ToUnicode 69 0 R>>
|
|
||||||
endobj
|
|
||||||
38 0 obj
|
|
||||||
<</Type/Font/Subtype/CIDFontType2/BaseFont/KBDGOZ+MicrosoftYaHeiUI-Bold/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)/Supplement 0>>/FontDescriptor 39 0 R/DW 0/CIDToGIDMap/Identity/W[0 0 697.2656 1 26 1000]>>
|
|
||||||
endobj
|
|
||||||
39 0 obj
|
|
||||||
<</Type/FontDescriptor/FontName/KBDGOZ+MicrosoftYaHeiUI-Bold/Flags 131076/FontBBox[2.9296875 -137.20703 996.09375 837.40234]/ItalicAngle 0/Ascent 812.0117/Descent -253.41797/CapHeight 756.34766/StemV 168.6/CIDSet 68 0 R/FontFile2 70 0 R>>
|
|
||||||
endobj
|
|
||||||
40 0 obj
|
|
||||||
<</Type/Font/Subtype/Type0/BaseFont/EOVZXV+SegoeUIVariable/Encoding/Identity-H/DescendantFonts[41 0 R]/ToUnicode 72 0 R>>
|
|
||||||
endobj
|
|
||||||
41 0 obj
|
|
||||||
<</Type/Font/Subtype/CIDFontType2/BaseFont/EOVZXV+SegoeUIVariable/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)/Supplement 0>>/FontDescriptor 42 0 R/DW 0/CIDToGIDMap/Identity/W[0 0 642.08984 1 1 260.2539 2 2 267.57812]>>
|
|
||||||
endobj
|
|
||||||
42 0 obj
|
|
||||||
<</Type/FontDescriptor/FontName/EOVZXV+SegoeUIVariable/Flags 131076/FontBBox[42.96875 0 562.5 682.6172]/ItalicAngle 0/Ascent 728.02734/Descent -210.44922/CapHeight 700.1953/StemV 95.4/CIDSet 71 0 R/FontFile2 73 0 R>>
|
|
||||||
endobj
|
|
||||||
43 0 obj
|
|
||||||
<</Type/Font/Subtype/Type0/BaseFont/XZKLJD+MicrosoftYaHeiUI/Encoding/Identity-H/DescendantFonts[44 0 R]/ToUnicode 75 0 R>>
|
|
||||||
endobj
|
|
||||||
44 0 obj
|
|
||||||
<</Type/Font/Subtype/CIDFontType2/BaseFont/XZKLJD+MicrosoftYaHeiUI/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)/Supplement 0>>/FontDescriptor 45 0 R/DW 0/CIDToGIDMap/Identity/W[0 0 697.2656 1 84 1000]>>
|
|
||||||
endobj
|
|
||||||
45 0 obj
|
|
||||||
<</Type/FontDescriptor/FontName/XZKLJD+MicrosoftYaHeiUI/Flags 131076/FontBBox[1.953125 -143.0664 997.0703 843.2617]/ItalicAngle 0/Ascent 812.0117/Descent -253.41797/CapHeight 756.34766/StemV 95.4/CIDSet 74 0 R/FontFile2 76 0 R>>
|
|
||||||
endobj
|
|
||||||
46 0 obj
|
|
||||||
<</Type/Font/Subtype/Type0/BaseFont/WXVVVC+Consolas/Encoding/Identity-H/DescendantFonts[47 0 R]/ToUnicode 78 0 R>>
|
|
||||||
endobj
|
|
||||||
47 0 obj
|
|
||||||
<</Type/Font/Subtype/CIDFontType2/BaseFont/WXVVVC+Consolas/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)/Supplement 0>>/FontDescriptor 48 0 R/DW 0/CIDToGIDMap/Identity/W[0 21 549.8047]>>
|
|
||||||
endobj
|
|
||||||
48 0 obj
|
|
||||||
<</Type/FontDescriptor/FontName/WXVVVC+Consolas/Flags 131077/FontBBox[4.8828125 -8.7890625 544.9219 646.97266]/ItalicAngle 0/Ascent 742.6758/Descent -257.32422/CapHeight 638.1836/StemV 95.4/CIDSet 77 0 R/FontFile2 79 0 R>>
|
|
||||||
endobj
|
|
||||||
49 0 obj
|
|
||||||
<</Type/Font/Subtype/Type0/BaseFont/BAYDIT+SegoeUIVariable/Encoding/Identity-H/DescendantFonts[50 0 R]/ToUnicode 81 0 R>>
|
|
||||||
endobj
|
|
||||||
50 0 obj
|
|
||||||
<</Type/Font/Subtype/CIDFontType2/BaseFont/BAYDIT+SegoeUIVariable/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)/Supplement 0>>/FontDescriptor 51 0 R/DW 0/CIDToGIDMap/Identity/W[0 0 645.5078 1 1 737.3047 2 2 435.0586]>>
|
|
||||||
endobj
|
|
||||||
51 0 obj
|
|
||||||
<</Type/FontDescriptor/FontName/BAYDIT+SegoeUIVariable/Flags 131076/FontBBox[4.8828125 0 701.1719 715.8203]/ItalicAngle 0/Ascent 728.02734/Descent -210.44922/CapHeight 700.1953/StemV 95.4/CIDSet 80 0 R/FontFile2 82 0 R>>
|
|
||||||
endobj
|
|
||||||
52 0 obj
|
|
||||||
<</Type/Font/Subtype/Type0/BaseFont/VEVAMH+SegoeUIVariable/Encoding/Identity-H/DescendantFonts[53 0 R]/ToUnicode 84 0 R>>
|
|
||||||
endobj
|
|
||||||
53 0 obj
|
|
||||||
<</Type/Font/Subtype/CIDFontType2/BaseFont/VEVAMH+SegoeUIVariable/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)/Supplement 0>>/FontDescriptor 54 0 R/DW 0/CIDToGIDMap/Identity/W[0 0 641.1133 1 1 257.32422 2 2 266.60156 3 3 448.2422]>>
|
|
||||||
endobj
|
|
||||||
54 0 obj
|
|
||||||
<</Type/FontDescriptor/FontName/VEVAMH+SegoeUIVariable/Flags 131076/FontBBox[-6.3476562 -99.609375 562.0117 700.1953]/ItalicAngle 0/Ascent 728.02734/Descent -210.44922/CapHeight 700.1953/StemV 95.4/CIDSet 83 0 R/FontFile2 85 0 R>>
|
|
||||||
endobj
|
|
||||||
55 0 obj
|
|
||||||
<</Type/Font/Subtype/Type0/BaseFont/FZYZJG+SegoeUIVariable/Encoding/Identity-H/DescendantFonts[56 0 R]/ToUnicode 87 0 R>>
|
|
||||||
endobj
|
|
||||||
56 0 obj
|
|
||||||
<</Type/Font/Subtype/CIDFontType2/BaseFont/FZYZJG+SegoeUIVariable/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)/Supplement 0>>/FontDescriptor 57 0 R/DW 0/CIDToGIDMap/Identity/W[0 0 643.5547 1 1 267.08984 2 2 705.0781]>>
|
|
||||||
endobj
|
|
||||||
57 0 obj
|
|
||||||
<</Type/FontDescriptor/FontName/FZYZJG+SegoeUIVariable/Flags 131076/FontBBox[80.078125 0 590.33203 682.6172]/ItalicAngle 0/Ascent 728.02734/Descent -210.44922/CapHeight 700.1953/StemV 95.4/CIDSet 86 0 R/FontFile2 88 0 R>>
|
|
||||||
endobj
|
|
||||||
58 0 obj
|
|
||||||
<</Type/Font/Subtype/Type0/BaseFont/XWXGBP+SegoeUIVariable/Encoding/Identity-H/DescendantFonts[59 0 R]/ToUnicode 90 0 R>>
|
|
||||||
endobj
|
|
||||||
59 0 obj
|
|
||||||
<</Type/Font/Subtype/CIDFontType2/BaseFont/XWXGBP+SegoeUIVariable/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)/Supplement 0>>/FontDescriptor 60 0 R/DW 0/CIDToGIDMap/Identity/W[0 0 645.5078 1 1 273.92578 2 2 389.64844]>>
|
|
||||||
endobj
|
|
||||||
60 0 obj
|
|
||||||
<</Type/FontDescriptor/FontName/XWXGBP+SegoeUIVariable/Flags 131076/FontBBox[-3.90625 -104.00391 564.4531 700.1953]/ItalicAngle 0/Ascent 728.02734/Descent -210.44922/CapHeight 700.1953/StemV 95.4/CIDSet 89 0 R/FontFile2 91 0 R>>
|
|
||||||
endobj
|
|
||||||
61 0 obj
|
|
||||||
<</Type/Font/Subtype/Type0/BaseFont/UBLLTL+SegoeUIVariable/Encoding/Identity-H/DescendantFonts[62 0 R]/ToUnicode 93 0 R>>
|
|
||||||
endobj
|
|
||||||
62 0 obj
|
|
||||||
<</Type/Font/Subtype/CIDFontType2/BaseFont/UBLLTL+SegoeUIVariable/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)/Supplement 0>>/FontDescriptor 63 0 R/DW 0/CIDToGIDMap/Identity/W[0 0 653.3203 1 1 273.92578 2 2 1007.8125 3 3 363.76953 4 4 540.03906 5 5 328.125 6 6 439.45312 7 7 400.39062]>>
|
|
||||||
endobj
|
|
||||||
63 0 obj
|
|
||||||
<</Type/FontDescriptor/FontName/UBLLTL+SegoeUIVariable/Flags 131076/FontBBox[-1.953125 -104.98047 1003.90625 751.9531]/ItalicAngle 0/Ascent 728.02734/Descent -210.44922/CapHeight 700.1953/StemV 95.4/CIDSet 92 0 R/FontFile2 94 0 R>>
|
|
||||||
endobj
|
|
||||||
64 0 obj
|
|
||||||
<</Type/Font/Subtype/Type0/BaseFont/SDHMZN+DejaVuSansMono/Encoding/Identity-H/DescendantFonts[65 0 R]/ToUnicode 96 0 R>>
|
|
||||||
endobj
|
|
||||||
65 0 obj
|
|
||||||
<</Type/Font/Subtype/CIDFontType2/BaseFont/SDHMZN+DejaVuSansMono/CIDSystemInfo<</Registry(Adobe)/Ordering(Identity)/Supplement 0>>/FontDescriptor 66 0 R/DW 0/CIDToGIDMap/Identity/W[0 12 602.0508]>>
|
|
||||||
endobj
|
|
||||||
66 0 obj
|
|
||||||
<</Type/FontDescriptor/FontName/SDHMZN+DejaVuSansMono/Flags 131077/FontBBox[0 -235.83984 602.0508 765.1367]/ItalicAngle 0/Ascent 759.7656/Descent -240.23438/CapHeight 759.7656/StemV 95.4/CIDSet 95 0 R/FontFile2 97 0 R>>
|
|
||||||
endobj
|
|
||||||
67 0 obj
|
|
||||||
<</Type/Page/Resources 36 0 R/MediaBox[0 0 595.2756 841.8898]/StructParents 0/Parent 1 0 R/Contents 98 0 R>>
|
|
||||||
endobj
|
|
||||||
68 0 obj
|
|
||||||
<</Length 12/Filter/FlateDecode>>
|
|
||||||
stream
|
|
||||||
xœûÿÿÿ | |||||||