2
0
0

文档写作规范(用本仓库模板)

2026-09-13
2026-09-13
文章摘要
|

来源:halo-kb/知识库架构设计.md## D) Markdown 文档模板(原文 7388 字符)

D) Markdown 文档模板

D.1 先确定「本实例到底支持什么写作格式」(已核实)

事实证据
Halo 原生文章的正文存储是 HTML实测本实例唯一文章 Hello HalorawTypeHTMLraw 字段内容是 <h2>…</h2><p>…</p>(通过 Halo API 读取)
Halo 内置编辑器是富文本,可通过插件替换官方文档 文章:「编辑器切换:如果安装了其他的编辑器插件,那么就可以在这个位置选择所需的编辑器」,并给出应用市场 ?tag=editor 入口
MiniDocs 的文档存储是 MarkdownKnowledgeBaseDoc.spec.raw 存原文,spec.content 存编辑器渲染出的 HTML;插件自带 MarkdownEditor.vue

结论与模板策略

  • Halo 文章 → 用 HTML 版模板(可直接粘贴进内置编辑器的「源码」视图;也可正常用富文本工具栏编辑)。
  • MiniDocs 文档 → 用 Markdown 版模板(插件自带 Markdown 编辑器)。
  • 仓库里另存的 .md 文件(如 intranet-tunnel 的 docs/用 Markdown 版,与 MiniDocs 保持一致。

⚠️ 关于 front-matter:Halo 原生文章不使用 front-matter——标题、分类、标签、摘要、封面、可见性等全部在「文章设置」对话框里填写,正文只存内容本身(见官方文档「文章设置」小节)。front-matter 只在通过插件从外部文件导入时才有意义(例如社区插件 plugin-content-tools 的 Markdown 导入)。该插件在本实例未安装,其 front-matter 字段名我未核实 → 标为「未确认」本方案的替代做法:在正文开头放一个「元信息块」(普通表格/列表),承载"适用版本 / 最后验证时间 / 环境",它不依赖任何插件,在 Halo 与 MiniDocs 两边都能正常渲染。这比依赖未确认的 front-matter 更稳。 MiniDocs 侧也不需要 front-matter:title / slug / summary / tags / parentName 都在导入参数与实体字段里。

D.2 模板 ①-a:技术笔记 / 排错记录(HTML 版,用于 Halo 文章)

适用:"现象 → 根因 → 修复 → 判据"型文章,这是知识库中价值最高的一类。

<blockquote><p><strong>TL;DR</strong>:一句话说清根因与修法,让读者 5 秒判断是否与他相关。</p></blockquote>

<h2>元信息</h2>
<ul>
  <li><strong>适用版本</strong>:intranet-tunnel v1.2.1 / Halo 2.26.1 / PostgreSQL 15.4</li>
  <li><strong>最后验证时间</strong>:2026-09-13</li>
  <li><strong>环境</strong>:Ubuntu 24.04.4 LTS,Docker 27.x,部署目录 <code>/home/docker/&lt;项目名&gt;/</code></li>
</ul>

<h2>现象</h2>
<p>用户视角看到了什么。要写<strong>可观察的事实</strong>(报错原文、界面表现、返回值),不要写推测。</p>
<pre><code class="language-text">把原始报错整段贴进来,不要截断、不要"美化"。</code></pre>

<h2>排查过程</h2>
<ol>
  <li><strong>先确认 X</strong>:执行 <code>docker inspect &lt;容器&gt; --format '{{.State.ExitCode}}'</code>,结果 <code>0</code> → 排除崩溃。</li>
  <li><strong>再确认 Y</strong>:……(写明"当时以为是什么、为什么排除")</li>
</ol>
<blockquote><p>⚠️ 踩坑提示:这里写"看似像 A 问题其实不是"的分叉点——这是本文最有价值的部分。</p></blockquote>

<h2>根因</h2>
<p>机制层面的解释:<strong>哪一行代码 / 哪一个配置项 / 哪一条链路</strong>导致了现象。附上关键代码或配置片段。</p>
<pre><code class="language-go">// 只贴关键几行,标注文件路径
// server/internal/proxy/tunnel_stats.go
func (c *Collector) AddIn(name string, n int64) { /* ... */ }</code></pre>

<h2>修复</h2>
<pre><code class="language-bash"># 可直接复制的命令,按顺序执行
docker compose build tunnel-server
docker compose up -d tunnel-server</code></pre>
<p>说明为什么这样改,以及<strong>为什么不是另一种改法</strong>。</p>

<h2>验证(判据)</h2>
<ul>
  <li>✅ 正向断言:访问隧道域名 3 次,<code>bytes_in/bytes_out</code> 增量非 0。</li>
  <li>✅ <strong>反向断言</strong>:未被访问的隧道统计<strong>仍为 0</strong>(只看总量涨了会把"统计挂错了隧道"放过去)。</li>
  <li>✅ 操作本身的成功信号:接口返回 200,且读回值符合预期。</li>
</ul>

<h2>通用教训</h2>
<p>能迁移到其他场景的那一条原则(可被未来的自己在别的项目里复用)。</p>

<h2>相关</h2>
<ul>
  <li><a href="/archives/xxx">相关文章</a></li>
  <li><a href="/docs/view/tech-docs/tunnel-troubleshoot">文档库 · 隧道排错手册</a></li>
</ul>

D.3 模板 ①-b:同一篇内容(Markdown 版,用于 MiniDocs / 仓库)

> **TL;DR**:一句话说清根因与修法。

## 元信息

| 项 | 值 |
|---|---|
| 适用版本 | intranet-tunnel v1.2.1 / Halo 2.26.1 |
| 最后验证时间 | 2026-09-13 |
| 环境 | Ubuntu 24.04.4 / Docker 27.x |

## 现象

可观察的事实 + 原始报错:

```text
Error: command timed out after 30 seconds

排查过程

  1. 先确认进程状态pgrep -af acme.sh → 进程仍在运行,排除"没启动"。
  2. 再确认超时层级:外层 sh 被杀,子进程存活 → 超时来自 CLI 而非任务本身。

⚠️ 踩坑提示:把"看似像 A 其实不是 A"的分叉点写在这里。

根因

机制层面的解释(哪一行代码 / 哪一个配置项)。

修复

nohup ./long-task.sh > /tmp/task.log 2>&1 &

验证

  • ✅ 正向断言:……
  • ✅ 反向断言:……

> **注意**:Markdown 代码块的围栏嵌套在本文档里展示时会冲突,实际写入时按正常 ```` ``` ```` 使用。

### D.4 模板 ②:项目文档 / README 风格(Markdown,用于 MiniDocs 与代码仓库)

````markdown
# intranet-tunnel 服务端部署手册

| 项 | 值 |
|---|---|
| 文档状态 | 现行有效 |
| 适用版本 | v1.2.1 及以上 |
| 最后验证 | 2026-09-13(真实环境验证通过) |
| 维护人 | sushike |

## 这是什么

一段话说清:这个项目解决什么问题、给谁用、不做什么。

## 架构

```text
浏览器 ──TLS──> 宝塔 nginx ──> 127.0.0.1:48080 内置反代 ──> 隧道 ──> 内网服务
                                   │
                                   └── 控制面 :47800 / 面板 :47801

快速开始

mkdir -p /home/docker/intranet-tunnel && cd /home/docker/intranet-tunnel
cp .env.example .env    # 再填入真实值,切勿提交
docker compose up -d tunnel-server postgres db-backup

⚠️ 务必显式指定服务名:默认 up -d 会连带启动 tunnel-nginx,而该机的 80/443 由宝塔接管。

配置项

变量必填默认说明
DB_PASSWORD数据库口令,不要写进版本库
TUNNEL_DOMAIN隧道基础域名,前缀写法由它补全
DDNS_IP_APIS内置列表留空需整行注释,显式置空会导致启动失败

部署步骤

  1. 准备目录与权限
  2. 生成 .env
  3. 启动并确认日志
  4. 接入 nginx 与证书

验证docker inspect <容器> --format '{{.State.Status}}' 返回 running

常见问题

症状原因处理
bind source path does not exist旧容器记录了旧目录docker rm -f 后重新 up
面板显示裸前缀域名展示路径未做域名补全升级到 v1.0.3+

变更记录

日期版本变更
2026-09-131.2.1修复登录后无反应

### D.5 模板 ③:教程 / 长文(HTML 版,用于 Halo 文章)

Ethereal 的文章页**自动生成目录**,条件是标题层级正确 + 主题设置开启(本实例 `post.toc.enable_toc = true`、`toc_depth = 2`,即**目录抓取到 H2 深度**)。因此长文请**统一用 H2 作为主章节**。

```html
<h2>这篇教程适合谁</h2>
<p>前置知识、需要准备的东西、预计耗时、最终能达成什么效果。</p>
<ul>
  <li><strong>前置</strong>:一台能跑 Docker 的机器,一个已备案的域名。</li>
  <li><strong>产出</strong>:可在公网访问的自建服务。</li>
</ul>

<h2>第一步:准备工作</h2>
<p>说清"为什么需要这一步",再给命令:</p>
<pre><code class="language-bash">ssh root@&lt;服务器IP&gt;
mkdir -p /home/docker/&lt;项目名&gt;</code></pre>
<p><strong>验证</strong>:<code>ls -ld /home/docker/&lt;项目名&gt;</code> 输出目录存在且属主正确。</p>

<h2>第二步:…(依次推进,每步都必须有验证判据)</h2>

<h2>原理补充(可跳过)</h2>
<blockquote><p>💡 这一段解释"为什么这样做有效",不影响操作,供后续排错时回看。</p></blockquote>

<h2>常见坑</h2>
<ol>
  <li><strong>坑一</strong>:现象 → 原因 → 处理。</li>
  <li><strong>坑二</strong>:……</li>
</ol>

<h2>小结</h2>
<p>三句话总结,并给出下一步可做的事(附内链)。</p>

D.6 各要素的写法规范

自动目录导航

做法
触发条件本实例 Ethereal 的「文章设置 → 目录」已开启(enable_toc = true),无需在正文里写目录
标题层级H2 为主章节toc_depth = 2)。需要更细的层级时,到「主题设置 → 文章 → 目录 → 目录最大深度」调大
标题 IDHalo 自动为标题生成 id(实测 Hello Halo 渲染出 <h2 id="hello-halo">),不要手写锚点,跨文档引用用完整 URL
移动端主题在无可见目录时显示右下角目录悬浮按钮(layout.floatingButtons.enable_toc = true

代码高亮

  • HTML 版<pre><code class="language-go">…</code></pre>——语言 class 必须写对,高亮器靠它识别语言。
  • Markdown 版 `go 围栏,信息串即语言名。
  • 本实例相关事实:Ethereal 官方 README 把「Shiki 代码高亮」插件(应用市场 app-kzloktzn)列为推荐搭配插件,用于"在内容页高亮显示代码块";据既有调研,本实例前台已加载 shiki。因此只需保证语言 class 正确,不需要在正文里引入任何高亮脚本或额外 CSS
  • 行号、高亮特定行等增强能力取决于该插件的实际实现,未逐一核实 → 未确认;不要写进模板。

提示框 / 警告框

  • HTML 版(推荐,确定可用):用引用块 + 符号前缀,主题的 prose 排版会渲染为引用样式:
  <blockquote><p>⚠️ 注意:覆盖正在运行的 exe 会失败,先确认程序没在跑。</p></blockquote>
  <blockquote><p>💡 提示:本机未安装 make,直接用 git 命令。</p></blockquote>
  • Markdown 版(用于 MiniDocs):同样用 > ⚠️ … 引用块——这是确定可行的写法
  • :::info 容器语法:MiniDocs 的 Markdown 渲染器是否支持该语法、Halo 文章渲染管线是否支持,均未确认(Halo 官方文档站自己使用该语法,但那不能证明站点的文章渲染也支持)。建议不要依赖它,需要强视觉提示时优先用引用块。

图片与附件引用

场景做法
文章内插图始终用编辑器的「插入图片」上传,不要手写 URL。Halo 会自动生成附件记录与访问地址
MiniDocs 文档内插图同上,用插件的图片上传能力;跨知识库引用同一张图时建议用 Halo 附件的稳定地址(具体地址形式未在本实例核实到——当前实例附件数为 0,无样本 → 未确认
封面图在「文章设置 → 封面图」上传,不要写进正文。主题 post.contentDisplay.showCover = true 会在正文上方显示封面
附件文件(zip/tar 等)用编辑器插入为链接;不要用第三方网盘直链(会失效且不可控)
图片优化本实例「主题设置 → 速度优化 → 图片处理服务」当前为 none(不处理)。若日后接入 CDN/OSS,正文图片会按 article_image_width(默认 1200px)压缩——接入前先确认原图不被过度压缩


来源:halo-kb/README.md## 附录 A:本次产出物与验证方式(原文 2704 字符)

附录 A:本次产出物与验证方式

A.1 本次任务改动了什么

本任务是纯文档整合,对 Halo 实例与 NAS 零改动。

类别内容
本次新建H:\Works\halo-kb\README.md(本文件,总纲交付文档)
本次未改动Halo / PostgreSQL 容器、NAS /vol1/1000/docker/halo/ 下任何文件、Gitea 任何数据、D:\DSH Desktop\resources\ 下任何文件
本次只读取同目录 10 份报告 + scripts/ 下全部脚本与日志

本文件与既有报告的关系:本文件是总纲与索引,把 10 份报告与脚本整合成一条可复现路径; 细节与原始证据仍在各专项报告中,两者冲突时以专项报告为准(本文件若与专项报告不一致,属本文件的转写错误)。

专项报告本文件对应章节
实例现状基线.md第二章、第四章
插件选型调研.md第四章、第六章、第十三章 A/B 组
知识库架构设计.md第五章、第六章、第七章
分类标签落地记录.md第五章
minidocs-落地记录.md第五章 5.6、第十章
页面与展示配置记录.md第七章
AI能力验证.md第九章
gitea-集成方案.md + gitea-同步落地记录.md第八章
备份运维与安全.md第十一章、第十二章

A.2 如何验证本文档

# ① 文档结构完整(应输出 15 个章节标题 + 附录)
Select-String -Path H:\Works\halo-kb\README.md -Pattern '^## ' | Measure-Object

# ② 【硬约束】密钥形态扫描 —— 必须 0 命中
#    注意:Select-String -Path <目录>\* 会把子目录当成文件而报“访问被拒绝”,那是噪声不是命中;
#    要覆盖全部文件(含隐藏文件)请用下面这条 -File -Force 的写法:
Get-ChildItem -Path H:\Works\halo-kb -Recurse -File -Force |
  Select-String -Pattern 'pat_[A-Za-z0-9_\-\.]{80,}|hmcp_[A-Za-z0-9_-]{60,}|sk-[A-Za-z0-9]{20,}' -AllMatches

# ③ 本文档不含真实凭据(应只在说明文字里出现占位符)
Select-String -Path H:\Works\halo-kb\README.md -Pattern '<TOKEN>|<REDACTED>'

# ④ 章节顺序检查(应依次出现 一 ~ 十五)
Select-String -Path H:\Works\halo-kb\README.md -Pattern '^## (一|二|三|四|五|六|七|八|九|十|十一|十二|十三|十四|十五)、'

判据

  • 必须 0 命中;若有命中立即清除并复验;
  • ④ 应输出 15 行,顺序为 一 二 三 四 五 六 七 八 九 十 十一 十二 十三 十四 十五。

A.3 复现整套知识库的验收测试(按章节顺序)

步骤命令 / 动作期望结果
1halo plugin list(CLI)能列出插件 ⇒ CLI 认证与地址正确
2python create_taxonomy.py --verify-only分类 29(8 一级 + 20 二级)/ 标签 45,73 条断言全通过
3python create_taxonomy.py(重跑)新建 0、跳过 73、失败 0(幂等)
4.\minidocs_setup.ps1 -VerifyOnly知识库 1 个、文档 38 个、exit=0
5python configure_site_display.py verify//docs/portfolio/about/skills/timeline/rss.xml 全部 [OK] 200,结论行「全部通过」
6python gitea_to_halo.py --self-test「自测全部通过」(48 项)
7python verify-sync.py「回读校验全部通过」(44 项)
8`curl.exe -s --noproxy "*" http://<内网IP>:28090/portfolio \Select-String '共 . 个项目'`共 2 个项目
9./scripts/halo-restore-verify.sh「✅ 恢复验证通过」,表数 34=34、extensions 391=391
10./scripts/halo-healthcheck.sh「✅ 全部通过」(10 项)
11curl.exe -s -o NUL -w "%{http_code}" --noproxy "*" http://<内网IP>:28090/apis/api.console.halo.run/v1alpha1/users必须 302(出现 200 = 严重问题)

第 4、5、6、7、9、10 步都是幂等/只读的,可以随时重复执行用于回归。 唯一的写操作是第 3 步(且它对已存在的数据只跳过、不修改)。


文档结束。 本文档所有结论均可回溯到同目录的专项报告; 标注【未确认】的项请勿直接用于决策,标注【推断】的项请先验证再依赖。

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或者给予支持!

评论