Skip to content

ZMBlog · 使用文档 ​

适用版本:ZMBlog v2.3.1  阅读对象:站点所有者、内容编辑、主题与插件使用者


目录 ​

  1. 产品概述
  2. 五分钟上手
  3. 后台界面总览
  4. 写作与内容管理
  5. 分类与标签
  6. 评论管理
  7. 附件管理
  8. 用户与权限
  9. 站点设置
  10. 主题使用与切换
  11. 模板在线编辑
  12. 插件使用
  13. 伪静态设置
  14. 数据导入导出
  15. 操作日志
  16. REST API 速查
  17. 缓存与响应头
  18. 常见问题

1. 产品概述 ​

ZMBlog是一套自研的轻量级博客内核,特点是:

特性说明
零第三方依赖仅需 Node.js,数据库用内置 node:sqlite,无npm 包、无编译步骤
伪静态路由32 条内置规则,正则与路由表达式双栏配置,可视化排序与预览
插件系统过滤器 / 动作两类钩子,可注入模板函数、注册后台配置面板
主题系统模板文件 + 主题函数 + 主题配置,支持后台在线编辑与安全闸门
内容形态文章、独立页面、分类、标签、评论、附件、自定义字段
发布控制草稿、待审核、定时发布、私密、密码保护、置顶
安全基线scrypt 密码哈希、CSRF 校验、登录限流、上传白名单、安全响应头

程序目录职责:

  • themes/ —— 主题(可自由增删)
  • plugins/ —— 插件(可自由增删)
  • data/ —— 运行时数据:zmblog.db 数据库、uploads/ 上传文件、日志

2. 五分钟上手 ​

2.1 启动 ​

bash
node server.js

默认监听 http://localhost:3000。若端口被占用:

bash
PORT=8080 node server.js

2.2 完成安装 ​

首次访问会自动跳转到安装向导,依次五步:

  1. 环境检测 —— 自动校验 Node 版本、node:sqlite 可用性、目录可写性、数据库可读写
  2. 创建管理员 —— 填写用户名、昵称、邮箱、密码(前端实时强度提示,后端要求≥8 位且强度达标)
  3. 站点信息 —— 站点标题、描述、站点地址、作者昵称、页脚文案
  4. 伪静态 —— 选择预设方案(默认 32 条规则),也可稍后在后台自定义
  5. 完成 —— 可勾选生成示例内容,便于熟悉各功能

安装完成后自动标记 installed,此后访问根路径直接进入站点,安装入口关闭。

2.3 登录后台 ​

访问 http://localhost:3000/admin/,用第2 步创建的管理员账号登录。


3. 后台界面总览 ​

后台为单页应用,左侧导航分区如下:

分区功能
仪表盘文章 / 页面 / 评论 / 分类 / 标签数量统计、主题与插件状态、最近操作
文章列表检索、批量状态切换、删除、编辑器
页面独立页面管理(关于、友链等)
分类分类增删改、排序、别名设置
标签标签增删改、文章计数
评论评论列表、审核(通过 / 待审 / 垃圾 / 删除)、回复查看
附件管理上传、筛选、与文章 / 页面绑定、删除
用户用户增删改、角色分配、重置密码
设置站点信息、阅读设置、评论设置、伪静态、模板编辑器
主题主题切换、主题配置、模板文件在线编辑
插件插件列表、启用/停用、配置面板
日志操作日志检索与清空
数据导出 / 导入

4. 写作与内容管理 ​

4.1 新建文章 ​

后台「文章 → 新建」,主要字段:

字段说明
标题必填,留空自动记为「无标题」
别名URL标识,留空按标题生成;冲突时自动追加序号
正文支持 Markdown 渲染
摘要留空时自动截取;正文含 <!--more--> 时以该处为摘要终点
分类 / 标签可多选,标签输入后回车确认
发布时间可设为未来时间(定时发布)
状态发布 / 草稿 / 待审核 / 私密
访问密码填写后访客需输入密码才能查看
允许评论关闭后前台不显示评论表单
置顶置顶文章在首页优先展示
模板指定该篇使用的模板(默认 post)
自定义字段键值对,模板中通过 fields.xxx 访问

4.2 文章状态 ​

状态前台可见性
publish 发布所有人可见;若发布时间在未来,到时间才对访客可见(作者与管理员可预览)
draft 草稿仅作者与管理员可见,对匿名访客返回 404
pending 待审核同草稿
private 私密仅已登录用户可见,匿名访客 404

安全设计:草稿、私密、定时未到的文章,其正文不会出现在列表页、归档页、搜索结果、RSS/Atom 输出或页面源码中。

4.3 密码保护文章 ​

填写「访问密码」后:

  • 访客访问该文章 URL 会看到密码输入页
  • 输入正确密码后,本次会话内可访问
  • 密码错误返回提示,不泄露正文

4.4 编辑与删除 ​

  • 列表页可直接改状态,无需进入编辑
  • PUT 更新为局部更新:只提交需要修改的字段,未出现的字段保持原值(不会因漏传而清空正文)
  • 删除为级联友好:分类 / 标签下有文章时拒绝删除并提示数量;文章删除同时清理其自定义字段

4.5 自定义字段 ​

在编辑器底部添加任意键值对,例如:

subtitle=第一版修订
project_ref=ZD-2041
rating=9

模板中访问:

html
{{ post.fields.subtitle }}
{{ post.fields.rating }}

5. 分类与标签 ​

5.1 分类 ​

分类支持多级父子结构与排序值,用于组织文章主脉络。

  • 别名(slug)决定前台路径 /category/<别名>/
  • count 为该分类下文章数,由内核自动重算
  • 分类下仍有文章时,删除请求被拒绝并返回文章数
  • 删除父分类时会递归收集全部子孙分类

5.2 标签 ​

标签无层级,以别名唯一标识,前台路径 /tag/<别名>/。

分类与标签使用独立的关联表,不会互相污染——一篇文章只属于它显式指定的分类与标签。


6. 评论管理 ​

6.1 前台评论 ​

访客在文章页填写昵称、邮箱、内容提交;邮箱不会公开显示。URL 为选填项。

6.2 审核状态 ​

状态前台是否显示
approved 已通过显示
waiting 待审核不显示
spam 垃圾不显示

6.3 防垃圾 ​

  • 同一 IP 一分钟内提交上限(默认 10 条,可在「设置 → 评论」调整 commentRateLimit)
  • 评论内容中链接数超阈值自动判为垃圾
  • 文章处于草稿 / 待审核 / 私密 / 已关闭评论时不接受留言
  • 可在「设置 → 评论」开启「评论需审核」,新评论默认进入待审核

6.4 回复与嵌套 ​

评论支持以 parent 指向父评论,形成树形展示。父评论被删除时,子回复自动上提到顶层,不会丢失内容。

后台评论接口支持新建、编辑、删除,删除时连带清理子回复。


7. 附件管理 ​

「附件管理」页面(菜单图标 📎,旧「媒体」页已升级为此页)用于集中管理站内所有上传文件:

  • 任意白名单类型:jpg / png / gif / webp / bmp / ico / avif / pdf / txt / md / csv / json / xml / zip / gz / tar / 7z / mp3 / wav / ogg / mp4 / webm / mov / woff / woff2 / ttf / otf 等(可在设置中调整)
  • 始终拒绝 svg / html / js / php / sh / exe 等可执行或可内联执行类型(防存储型 XSS),后台设置也无法放开
  • 无扩展名时按文件头嗅探类型
  • 单文件上限默认 8 MB(可在「设置 → 附件上传」调整,范围 0.1–100 MB)
  • 文件名形如 <时间戳>-<随机串>.<扩展名>,存于 data/uploads/
  • 下载地址形如 /upload/<文件名>,可直接插入正文

列表支持按 全部 / 已绑定 / 未绑定、文件类型(图片 / 其他)筛选,并可搜索原文件名; 每项显示缩略图、类型、大小、归属文章,可复制链接、绑定 / 改绑到文章或页面、删除。

7.1 与文章 / 页面绑定 ​

  • 每个附件有唯一归属 cid:cid = 0 表示未绑定(游离素材),cid > 0 表示绑定到某篇文章或页面。
  • 在文章 / 页面编辑器里:点击「上传附件」上传后会直接绑定到本篇;也可「从附件库选」挑已有素材; 点「插入」会把链接写到正文光标处(图片则按 Markdown 图片语法插入)。保存时以当前列表为准, 被移出列表的附件自动解绑(文件保留)。
  • 新建内容时允许先上传附件(暂为未绑定),保存成功后统一绑定。
  • 删除文章只解绑、不删文件:素材完整留在附件库;删除附件才会连同磁盘文件一起删除。

7.2 前台展示 ​

默认主题(zm-default)会在正文下方自动输出「附件下载」区块。自定义主题可用:

html
{{#if post.attachments}}
  <ul>
  {{#each post.attachments}}
    <li><a href="{{ url }}" download>{{ original }}</a> <span>{{ sizeText }}</span></li>
  {{/each}}
  </ul>
{{/if}}

8. 用户与权限 ​

8.1 角色 ​

角色权限
administrator 管理员全部权限,含用户管理、插件、模板编辑
editor 编辑内容管理
contributor 投稿仅本人内容
subscriber 订阅者仅评论
visitor 访客匿名

后台 API 除公开接口外,统一要求管理员或编辑角色。

8.2 密码与会话 ​

  • 新密码要求≥8 位并通过强度校验
  • 修改密码后可选择「保留当前会话」或「注销全部会话」
  • 注销后旧会话立即失效
  • 「安全 → 会话」可查看当前账号的活跃会话(IP、User-Agent、创建时间)

8.3 登录保护 ​

同一 IP 连续登录失败达到阈值(默认 8 次)即锁定 900 秒,锁定期间即使密码正确也会被拒。


9. 站点设置 ​

「设置」分区包含:

分组主要项
站点信息站点标题、描述、站点地址、作者昵称、作者邮箱、页脚文案、备案号
阅读设置每页文章数、摘要长度、日期格式、时间格式、永久链接风格
评论设置是否需审核、防垃圾开关、IP 频率上限
媒体设置上传大小上限
附件上传允许的扩展名、单文件大小上限(0.1–100 MB)
SEOkeywords、description、站点地图与 robots 开关

永久链接风格:

值生成路径
origin(默认)文章 /<article>/<编号>.html、页面 /<别名>.html(对齐原站 / Typecho 风格)
default/archives/<别名>/
date/archives/<年>/<年-月>/<别名>/
id/archives/<数字 ID>/

风格切换后,新生成的链接按所选风格输出;内置伪静态同时保留 /archives/... 系列的旧链接 (别名 / 数字 / 年月归档均可命中),因此切换风格不会让历史链接立即失效。


10. 主题使用与切换 ​

默认随程序附带一套基础主题 zm-default;其余主题(zm-riven、zm-minimal)为独立分发,请到文档站「主题 / 插件」页下载,解压进 themes/ 目录后即可在后台看到。

官方主题:

主题特点
zm-default 默认主题随程序附带。三栏布局,含侧边栏、归档树、最新评论、目录样式,适合内容型站点
zm-riven Riven(移植版)需单独下载。移植自 Typecho 的 Riven 主题(对齐原站外观):首页 / 文章 / 归档 / 关于 / 友链 / 留言板 / 说说 / 走心等页面,含 PJAX 无刷新跳转、深色模式、评论徽章与 IP 属地、同源头像代理等
zm-minimal 极简主题需单独下载。单栏窄版,正文优先,适合写作与文档

切换主题:「主题」页选中目标主题 →「启用」。启用后立即生效,无需重启。

主题设置:每个主题可在 theme.json 的 config 中声明配置项(文本框 / 多行文本 / 下拉 / 复选 / 单选等),选中主题后进入「主题设置」即可看到表单,保存即时写入 themeConfig,模板中通过 themeConfig.xxx 读取;「恢复默认」可一键回到主题初始配置。zm-riven 提供 60 余项配置(站点外观、侧栏名片、文章页、页脚与导航、友情链接、关于页、评论、CDN 等)。


11. 模板在线编辑 ​

「主题 → 模板」可直接编辑主题内的模板文件:

  1. 选择文件(如 index.html)
  2. 在编辑器中修改,点击保存
  3. 前台刷新即可看到效果

可编辑类型:.html .htm .css .txt .md .svg 及无扩展名文件。

禁止写入(安全闸门):.js .mjs .cjs .json .node .exe .sh .php。原因是主题的 functions.js 会被 require 执行,允许写入即等价于远程代码执行。写入非白名单类型时接口直接拒绝。

所有模板路径均经归一化校验,禁止越出主题目录。

建议:在线编辑适合小改与实验;大改动请在本地用编辑器完成,并纳入版本管理。


12. 插件使用 ​

插件为独立分发:请到文档站「主题 / 插件」页下载所需插件,解压进 plugins/ 目录后即可在后台看到。官方插件:

插件作用
reading-enhance 阅读增强预计阅读时长、阅读速度、文章末尾附言、二级标题目录(演示内容过滤 / 模板函数 / 后台面板 / 配置项四种能力)
welcome 欢迎卡片首页欢迎卡片:访客属地 + 实时天气(和风天气或 Open-Meteo 免密钥)、自动收起、每 N 天一次
comment-notifier 评论邮件通知新评论 / 回复 / 待审核时发邮件(零依赖 SMTP、多套模板、异步队列)
links 友情链接友链管理(分类、图标、导入导出),并提供 /page/links 友链模板
email-subscribe 邮件订阅订阅确认 / 退订、人机验证、新文章群发
doge-upload 多吉云上传接管上传到多吉云对象存储,前台直接走 CDN

启用 / 停用:「插件」页面点击开关,即时生效,无需重启。

配置:每个插件可声明配置字段,插件页自动渲染表单(如阅读增强的阅读速度、欢迎卡片的天气 Key 等)。

停用后其所有过滤器、模板函数、面板一并移除,前台立即恢复为无插件状态。

插件的前台静态资源(/plugins/<插件名>/assets/**)由内核单独放行,其余插件源码一律不可直接访问。

开发自己的插件见《插件开发文档》。


13. 伪静态设置 ​

「设置 → 伪静态」提供规则的增删改、启停与排序。

13.1 规则结构 ​

字段说明
regex匹配请求路径的正则字符串
rule路由表达式,决定该路径映射到哪个模板与参数
enable是否启用
desc备注,仅用于识别

13.2 内置规则一览 ​

默认规则集共 32 条,按「原站风格(origin)优先 + 旧链接兼容」组织:

类别路径说明
首页/、/page/<数字>/首页与分页
文章/article/<数字编号>.html对齐原站
独立页面/<别名>.html对齐原站
分类/<分类别名>/、/<分类别名>/page/<数字>/对齐原站
标签/tag/<名称>/、/tag/<名称>/page/<数字>/对齐原站
搜索/search/、/search/<关键词>/、/search/<关键词>/page/<数字>/
订阅/feed/、/feed/rss/、/feed/atom/、/atomRSS 1.0(RDF)/ Atom
评论订阅/feed/article/<编号>.html、/feed/<别名>.html、/feed/rss/….html、/feed/atom/….html单篇内容评论订阅
归档/archive/、/archives/<年>/<月>/归档列表与年月归档
站点地图/sitemap、/sitemap.xml、/robots.txt
旧链接兼容/archives/<别名>、/archives/<年>/<月>/<别名>、/page/<别名>、/category/<分类> 等保证老地址不 404

完整的正则与路由表达式可在后台「设置 → 伪静态」的规则列表里逐条查看与编辑。

13.3 优先级 ​

规则顺序即优先级,自上而下首次命中即返回。 因此数字分页规则必须排在通用页面规则之前,日期型规则必须排在宽松别名规则之前。调整顺序时请保持这一约束。

13.4 自定义示例 ​

新增「按年份 + 分类名」访问文章:

正则:^/notes/([0-9]{4})/([^/]+)/?$
表达式:index.php/[archives]/[date:y]/[slug:slug]

新增后 /notes/2026/hello-world 即可访问该文章。

13.5 校验与重置 ​

  • 正则在保存时做语法校验,非法正则会被拒绝并返回具体错误
  • 「预览」可输入任意路由表达式,实时查看对应的示例路径
  • 「重置」恢复为 32 条默认规则

注意:修改规则后请同步调整反向链接策略。规则只影响 URL 生成与请求匹配,不自动重写已发布内容中的硬编码链接。


14. 数据导入导出 ​

「数据」页提供:

  • 导出 —— 生成完整 JSON 备份,含文章、页面、分类、标签、评论、选项等。为安全起见,导出内容不含 installed 标志与用户密码哈希,导入到新站点后仍需自行创建管理员。
  • 导入 —— 支持 merge(按 slug / 别名合并,覆盖同标识内容)与 replace(清空后导入)两种模式,导入前会校验数据结构版本。

建议在升级或迁移前先导出备份。


15. 操作日志 ​

「日志」页记录关键操作:登录成功/失败、文章增删改、评论审核、主题与插件启停、伪静态保存、模板写入、用户与设置变更等。

每条包含时间、类型、IP、简要信息。支持按类型筛选与一键清空。

排查问题时可先看日志,能快速定位是配置错误还是外部访问。


16. REST API 速查 ​

后台界面即基于同一套 REST API 构建,脚本化运维可直接调用。

通用约定

  • 基础路径 /api
  • 认证方式:登录后 Cookie(zmblog_session)
  • 所有写操作需附带会话绑定的 CSRF 令牌,请求头 X-CSRF-Token 或请求体 csrf 字段
  • 响应统一为 { "code": 0, "msg": "ok", "data": {...} };出错时 { "error": "说明" } 并带相应 HTTP 状态码

认证

方法路径说明
POST/api/auth/login登录(公开)
POST/api/auth/logout退出
GET/api/auth/me当前用户(公开)

内容

方法路径
GET / POST/api/posts
GET / PUT / DELETE/api/posts/:cid
POST/api/posts/:cid/fields
GET / POST/api/categories
PUT / DELETE/api/categories/:cid
GET / POST/api/tags
PUT / DELETE/api/tags/:mid
GET / POST/api/comments
PUT / DELETE/api/comments/:coid
POST/api/comments/public(公开)
GET/api/comments/recent

外观

方法路径说明
GET / POST/api/options站点配置
GET/api/themes主题列表
POST/api/themes/activate启用主题
GET / POST / DELETE/api/themes/file模板文件读写删
POST/api/themes/config主题配置
GET / POST/api/rewrite伪静态规则
POST/api/rewrite/reset重置规则
POST/api/rewrite/preview规则预览

扩展

方法路径
GET/api/plugins
POST/api/plugins/:name/toggle
POST/api/plugins/:name/config
GET / POST/api/users
PUT / DELETE/api/users/:uid
POST/api/password
GET/api/sessions

运维

方法路径说明
GET/api/dashboard统计
GET / POST/api/logs日志查询 / 清空
POST/api/upload上传附件(可带 ?cid= 直接绑定)
GET / DELETE/api/attachments附件列表(筛选)/ 删除(/api/media 为兼容别名)
POST/api/attachments/bind绑定 / 解绑({aid, cid},cid=0 为解绑)
GET/api/attachments/options当前允许类型与大小上限
GET/api/export导出
POST/api/import导入

调用示例

bash
# 登录并保存会话
curl -c cookie.txt -X POST http://localhost:3000/api/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"name":"admin","password":"你的密码"}'

# 读取 CSRF 令牌
CSRF=$(curl -b cookie.txt -s http://localhost:3000/api/auth/me | grep -o '"csrf":"[^"]*' | cut -d'"' -f4)

# 新建文章
curl -b cookie.txt -X POST http://localhost:3000/api/posts \
  -H 'Content-Type: application/json' \
  -H "X-CSRF-Token: $CSRF" \
  -d '{"title":"命令行文章","text":"正文内容","status":"publish"}'

17. 缓存与响应头 ​

程序在输出层统一约定缓存策略,便于经 CDN / 反向代理加速而不串数据:

  • 接口与后台(/api/*、/admin/*):一律 Cache-Control: no-store, no-cache, must-revalidate, max-age=0 —— 绝不缓存,避免串号 / 串数据。
  • HTML 页面:Cache-Control: no-cache,并对注入 nonce 之前的 HTML 计算弱 ETag;请求带 If-None-Match 且命中时返回 304(省流量)。
  • 静态资源:/admin/* 下未带 ?v= 指纹的 CSS/JS 为 no-cache(保证升级即时生效);带 ?v= 指纹或图片 / 字体等不可变资源则长缓存。
  • 安全响应头:CSP(每请求 nonce、只放行本站与自有 CDN)、X-Content-Type-Options、Referrer-Policy 等。

提示:若前面挂了 CDN,请让 CDN「按源站 Cache-Control」缓存;动态接口 / 后台已显式 no-store,不会被误缓存。


18. 常见问题 ​

Q:前台页面标题显示的是默认值,站点标题没生效。

A:属于历史版本缺陷。若在旧版本安装过,请到「设置 → 站点信息」重新保存一次站点标题即可修正。

Q:文章发布后前台还是 404。

A:检查三点——状态是否为「发布」;发布时间是否为未来时间(定时发布未到时间对访客不可见);URL 中的别名是否与后台一致。

Q:分类页 404。

A:确认已启用该分类、且文章状态为发布。分类路径使用分类别名而非名称。

Q:上传后文件不显示 / 下载 404。

A:确认使用的是上传接口返回的完整 /upload/<文件名> 路径;单文件需在大小上限内(默认 8 MB,可在设置调整); 扩展名需在允许名单内(SVG / HTML / JS 等出于安全考虑始终不支持)。

Q:忘记管理员密码。

A:服务器上删除 data/zmblog.db 后重新启动会进入安装向导重新初始化(会清空全部数据,请先备份)。

Q:修改伪静态规则后部分页面 404。

A:检查规则顺序。数字分页规则须在通用规则之前,日期型规则须在宽松别名规则之前;不确定时可点「重置」恢复默认再逐步调整。

Q:插件启用后前台报错。

A:查看 plugins/<插件名>/index.js 是否有语法错误(node --check 可验证),并在操作日志中确认报错发生时机。

Q:能否让某篇文章使用不同模板。

A:可以。编辑器「模板」字段可指定主题内已声明的模板名,如 post、page。

Q:多站点部署会不会互相干扰。

A:不会。为每个实例设置不同的 ZMBLOG_DATA_DIR 即可完全隔离数据目录。


相关文档 ​

ZMBlog · MIT License