Block 博客文章发布链路原理

2026年6月29日Block实践

<!-- block-content-capability: 1 -->

本文说明 Block 博客从管理员/Agent 登录后台读者在前台看到文章的完整链路,便于理解实现、排查问题或自行复现。

1. 架构总览

Block 采用前后端分离:三个前端/后端应用共用一套 NestJS API 与 PostgreSQL 数据库。

生产环境经 Nginx 统一入口 http://8.210.111.112/ 为前台,/admin/ 为后台,/api/v1/ 反代到 NestJS。

2. 第一步:登录后台

环节 说明
入口 /admin/login(生产:http://8.210.111.112/admin/login
API POST /api/v1/auth/login,请求体 { email, password }
成功响应 data.accessToken(短期)+ Set-Cookie: refresh_token(HttpOnly,路径 /api/v1/auth
前端存储 Access Token 写入 sessionStorage(键名 block_admin_access_token
后续请求 Axios 拦截器自动附加 Authorization: Bearer <token>,并 withCredentials: true 携带 Cookie

Access Token 过期时,Admin 会静默调用 POST /auth/refresh 换新 Token;Refresh 失效则跳转登录页。

要点:仅 Admin 账号可登录后台;前台没有读者登录路由。

3. 第二步:撰写与发布(Admin UI)

典型路径:文章管理 → 新建文章(路由 /admin/posts/new)。

UI 区域 对应数据字段
标题 title
Slug slug(可留空,后端按标题生成)
摘要 / 封面 / 分类 / 标签 excerpt / cover / categoryId / tagIds
Vditor 正文 contentMarkdown 纯文本,存 PostgreSQL Text
「保存草稿」 status: DRAFT
「发布」 status: PUBLISHED

点击发布时,Admin 调用:

  • 新建:POST /api/v1/admin/posts
  • 编辑:PATCH /api/v1/admin/posts/:id

均需 JwtAuthGuard(有效 Access Token)。正文插图可走 Vditor 上传或媒体库,最终仍写入 Markdown 的 ![](/uploads/...) 形式。

4. 第三步:API 如何处理写入

PostService.create / update 核心逻辑(简化):

  1. 校验 slug 格式与唯一性;关联分类/标签存在性
  2. 若未传 excerpt,从 Markdown 正文自动生成摘要
  3. status === PUBLISHED 时写入 publishedAt = now()
  4. prisma.post.create / update 持久化到 Post
  5. 若变为已发布,调用 seoCacheService.invalidate() 刷新 sitemap/feed 缓存

Post 表主要字段

字段 含义
title / slug 标题与 URL 标识(slug 全局唯一)
content Markdown 正文
status DRAFT / PUBLISHED / ARCHIVED
publishedAt 发布时间(仅已发布有值)
authorId 作者(当前登录 Admin)

草稿不会出现在公开 API 与前台列表中。

5. 第四步:读者如何看到文章

前台不直连数据库,只读公开 API:

场景 API 过滤条件
首页 / 列表 GET /api/v1/posts?page=&pageSize= status = PUBLISHED
详情页 GET /api/v1/posts/:slug 同上;草稿或非存在 slug → 404

前台路由注意:详情是单数 /post/:slug,不是 /posts/:slug

post-detail-view.vue 拉取详情后:

  1. MarkdownRenderercontent 转为 HTML(GFM 表格、Mermaid、代码高亮等)
  2. useHead 设置 SEO meta
  3. CommentSection 按 slug 挂载评论外挂(Waline/Giscus,可选)

6. 端到端时序(发布一篇新文)

7. Agent / curl 复现要点

与人工操作同一套 JWT,无单独 API Key。最小流程:

  1. POST /auth/login → 取 accessToken
  2. POST /admin/postsPATCH /admin/posts/:idcontent 为 Markdown 字符串
  3. GET /posts/{slug} 验证前台可读(或使用浏览器打开 /post/{slug}

详细 curl 与 Content Capability 语法见仓库 docs/dev/Agent写作指南.md

8. 常见问题

现象 可能原因
后台已发布,前台 404 slug 拼错;或访问了 /posts/slug 而非 /post/slug
列表看不到新文 status 仍为 DRAFT;或列表分页未翻到第一页
API 401 Access Token 过期且 Refresh 失败,需重新登录
改 slug 后评论丢失 评论外挂按 path/slug 绑定,已发布文章改 slug 需谨慎

本文由 Block 维护者通过 Admin 后台发布,内容与当前代码库 Phase 7 实现一致。